nomurabbitのブログ

nomurabbitのブログはITを中心にした技術ブログです。

nomurabbitのブログ

C#のDisposeメソッドとデストラクタが呼び出されるのはいつ?

<はじめに>
IDisposableインターフェースを実装したクラスを使用する場合、
using ステートメントを使ってリソースの解放を担保します。
そこで気になるのがDisposeメソッドとデストラクタの呼び出されるタイミング。

違うの?

一緒なの?

そこで、調べてみました。


<プログラム1>
■Dispose、デストラクタ呼び出しテスト

class Program
{
    static void Main(string[] args)
    {
        using (DisposeTest dTest = new DisposeTest())
        {
            Console.WriteLine("usingステートメントに入ったよ。");
        }
        Console.WriteLine("usingステートメントにから出たよ。");
    }
}

class DisposeTest : IDisposable
{
    ~DisposeTest()
    {
        Console.WriteLine("デストラクタが呼びだされたよ。");
    }

    public void Dispose()
    {
        Console.WriteLine("Disposeが呼びだされたよ。");
    }
}


<実行結果1>


usingステートメントを抜けたタイミングでDisposeメソッドが呼び出されるのは
想像通りだったのですが、デストラクタが呼び出されるのはもっと後なんですね。
ちょっと調べてみると下記のような記述が…


デストラクタ (C# プログラミング ガイド)
デストラクタがいつ呼び出されるかはガベージ コレクタによって決定されるため、プログラマは制御できません。


ん?ってことはGC呼び出せばそのタイミングでデストラクタ呼ばれるんじゃ…?
そう思ってプログラムを下記のように修正


<プログラム2>
■Dispose、デストラクタ呼び出しテスト_GC呼び出しver

class Program
{
    static void Main(string[] args)
    {
        using (DisposeTest dTest = new DisposeTest())
        {
            Console.WriteLine("usingステートメントに入ったよ。");
        }

        Console.WriteLine("usingステートメントにから出たよ。");

        // 下記2行を追加
        GC.Collect();
        Console.WriteLine("GCを実行したよ。デストラクタは呼び出されてるよね?");
    }
}

class DisposeTest : IDisposable
{
    ~DisposeTest()
    {
        Console.WriteLine("デストラクタが呼びだされたよ。");
    }

    public void Dispose()
    {
        Console.WriteLine("Disposeが呼びだされたよ。");
    }
}


<実行結果2>


<まとめ>
思ってたタイミングと違う!

やっぱりmsdnに書いてある通り、プログラムからは制御出来ませんでした。
正直デストラクタ使ってどうこうする機会はあまりないのですが、
興味本位で調べてみた結果は以上です。