GC コントロール

さてさて、C#インスタンスをなんとかコントロールしてみたいな、ということでこんな感じのコードを書いて見ます。

myClass instance = new myClass();
instance = null;
GC.Collect();

これで instance の Finalize が即呼び出されて開放されます。が、回収対象になっているインスタンス全てが対象になりますので、たまりにたまってるとかなり時間がかかる場合もあるかもしれません。結局 Finalize には何も書いてはいけないのですね。特別な処理が必要な場合は(慣例としての) Close か Dispose でと MS は言っていますし。

あと、昨日「Dispose は呼び出せません」とか書いていましたが間違ってました…。以下のようにすると外部から呼び出せます。

public class myClass : IDisposable
{
bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed) {
this.disposed = true;
if (disposing) {
// 終了処理
}
// その他の処理
}
}
~myClass()
{
Dispose(false);
}
}

上記コードは MSDN に載ってました。GC.SuppressFinalize は引数に指定したインスタンスGC の回収対象から外す為の指定で、disposed は Dispose が一度だけ実行されるようにする為のフラグです。面倒ですが「Disposeが呼ばれる≠インスタンスの破棄」なので仕方無いところでしょう。とりあえずはこんな感じで実装して using を使っていくことにします。using といえば以下のソースコードのようにすると一括で Dispose を呼び出してくれます。

using (myClass1 inst1 = new myClass1())
using (myClass2 inst2 = new myClass2())
using (myClass3 inst3 = new myClass3())
{
// 処理
}

@IT の会議室で見つけました。ぶら下がりを利用してるので自動整形ツールとかは使えなくなるかもしれませんが。

ということで、なんとかコントロールすることは出来るようですね。日ごろ PHP でプログラムを書いてる時は全然気にしてないのに、C# だと何故こんなに気になるのか自分でも良く分かりません…。DelphiIDE でプログラムを書いてるからかなぁ。*1

*1:良く考えたら Windows アプリと Web アプリのプロセスの寿命の違いですね。