83086


以下のコードの場合、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]


CC BY-SA 4.0
2021-10-14T00:49:14.280
83084
2021-10-15T04:54:57.423
40856
question
c#
C#のメモリ開放(Dispose)の必要性について


[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]


CC BY-SA 4.0
2021-10-14T01:20:26.417
83086
2021-10-14T01:20:26.417
8589
83084
answer


774RRさんの回答の通り、 **MemoryStreamに限っては**
Dispose()は必須ではありません。ですが、特殊な例ですので習慣としてDispose()できるもの(IDisposeを継承しているもの)は呼ぶ習慣をつけておいたほうが良いと思います。

Dispose()メソッドを呼ぶ代わりに[usingステートメント](https://docs.microsoft.com/ja-
jp/dotnet/csharp/language-reference/keywords/using-
statement)を使用する方法があります。Dispose()メソッドを直接呼ぶのではなくこのusingステートメントを使用することをおすすめします。  
以下の例では、usingのスコープを抜けるときに自動的にDispose()が呼ばれます。

[code]

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

C#8.0からはより簡単に以下のように記述できます。  
以下の例では、関数のスコープを抜けるときにDispose()が自動的に呼ばれます。

[code]

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


CC BY-SA 4.0
2021-10-14T07:28:44.323
83093
2021-10-14T07:35:15.423
2021-10-14T07:35:15.423
14817
14817
83084
answer


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)  
ほとんどバグとしか言いようがないですが、歴史的な経緯から修正されないようです…。


CC BY-SA 4.0
2021-10-14T11:24:08.413
83096
2021-10-14T11:24:08.413
4236
83084
answer


IDisposableを実装している場合は基本的にはDisposeすべきなのですが、既に回答にあるように解放の必要が無かったりするクラスもあったり、[HttpClient
クラス](https://docs.microsoft.com/ja-
jp/dotnet/api/system.net.http.httpclient?view=net-5.0)
のように単一インスタンスを作成して再利用するようドキュメントに記述されていたりする特殊な例もあったりしますので、初めて利用するクラスは仕様をきちんと確認した方がいいと思います。

> HttpClient は、1回インスタンス化し、アプリケーションの有効期間全体に再利用することを目的としています。 すべての要求に対して
> HttpClient クラスをインスタンス化すると、大量の読み込みで使用可能なソケットの数が枯渇します。 これにより、SocketException
> エラーが発生します。


CC BY-SA 4.0
2021-10-15T04:54:57.423
83106
2021-10-15T04:54:57.423
41943
83084
answer