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が呼びだされたよ。"); } }
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が呼びだされたよ。"); } }
<まとめ>
思ってたタイミングと違う!
やっぱりmsdnに書いてある通り、プログラムからは制御出来ませんでした。
正直デストラクタ使ってどうこうする機会はあまりないのですが、
興味本位で調べてみた結果は以上です。