C#のメモリ開放(Dispose)の必要性について


以下のコードの場合、memoryStreamはDisposeするべきですか？  
memoryStreamはこの関数内でしかスコープされていないので、問題ないですか？

[code]

    private byte[] ConvertToByte(Image image)
    {
        var memoryStream = new MemoryStream();
        image.Save(memoryStream, ImageFormat.Bmp);
        byte[] data = memoryStream.ToArray();
        //memoryStream.Dispose();
        return data;
    }
    
[/code]

以下のコードの場合明示的にメモリ開放(Dispose)しなきゃいけないところありますか？

[code]

    private Image GetImageFromClipBoard()
    {
        if (Clipboard.ContainsFileDropList())
        {
            StringCollection files = Clipboard.GetFileDropList();
    
            foreach (string fileName in files)
            {
                if (CommonFileDirLogic.IsFileExist(fileName))
                {
                    // ファイルコピーで得た画像
                    var fileImage = Image.FromFile(fileName);
                    return fileImage;
                }
            }
        }
    
        // PrintScreenでとったスクリーンショット
        Image printScreenImage = Clipboard.GetImage();
        return printScreenImage;
    }
    
[/code]




[MemoryStream](https://docs.microsoft.com/ja-
jp/dotnet/api/system.io.memorystream) によれば `IDisposable`
を実装していますが、破棄するリソースはないので `Dispose()` する必要はありません、と記載されています。

ごく普通に `Stream` を扱うコードを考えるに `MemoryStream` だけ `Dispose()`
してはいけない、ってのは不自然ですから（継承・派生してるってことはそういうこと） `Dispose()` しても問題はないです。

[code]

    class Program
    {
        static void Main(string[] args)
        {
            System.IO.FileStream s1 = new System.IO.FileStream("TestStream.txt", System.IO.FileMode.Create);
            StreamTest(s1);
            System.IO.MemoryStream s2 = new System.IO.MemoryStream();
            StreamTest(s2);
    
        }
        static void StreamTest(System.IO.Stream stream)
        {
            stream.Dispose();
        }
    }
    
[/code]




774RRさんおよびneeさんが指摘されるように、[`MemoryStream`クラス](https://docs.microsoft.com/ja-
jp/dotnet/api/system.io.memorystream?view=netframework-4.8)は`Dispose()`を呼ばなくてもよいレアな例です。

そしてneeさんが提案されるように`using`を使用するのが便利です。明示的に記述すると制御フローによって呼び出されないパターンが生じる危険性があります。特に例外発生時にも`using`であれば確実に`Dispose()`が呼び出されます。

逆のレアな例として`using`するべきでないクラスも存在します。.NETでWMIを扱う[`ManagementObject`クラス](https://docs.microsoft.com/ja-
jp/dotnet/api/system.management.managementobject?view=netframework-4.8)が該当します。このクラスは`IDisposable`を実装しているため`using`が使用可能ですが、`IDisposable`経由では正しくリソース解放されません。正しくリソース解放するためには`Dispose()`メソッドを明示的に呼び出す必要があります。

参考：
[`ManagementObject.Dispose()`](https://referencesource.microsoft.com/#System.Management/managementobject.cs,104)  
ほとんどバグとしか言いようがないですが、歴史的な経緯から修正されないようです…。

