これを見つけるためにildasmを実行しました:
using(Simple simp = new Simple())
{
Console.WriteLine("here");
}
これと同等の IL コードを生成します。
Simple simp = new Simple();
try
{
Console.WriteLine("here");
}
finally
{
if(simp != null)
{
simp.Dispose();
}
}
問題は、なぜ最終的に null をチェックするのかということです。finally ブロックは、try ブロックが実行された場合にのみ実行され、try ブロックは、Simple コンストラクターが成功した場合 (つまり、例外がスローされない場合) にのみ実行されます。この場合、simp は非 null になります。(Simple コンストラクターと try ブロックの先頭の間に何らかのステップが介在するのではないかという懸念がある場合、それは本当に問題になります。例外がスローされて、finally ブロックの実行がまったく妨げられる可能性があるからです。)それで、なぜ一体?
using ステートメントが try-finally よりも優れているかどうかの議論は (お願いします) 脇に置いて、try-finally ブロックを次のように記述します。
Simple simp = new Simple();
try
{
Console.WriteLine("here");
}
finally
{
simp.Dispose();
simp = null; // sanity-check in case I touch simp again
// because I don't rely on all classes
// necessarily throwing
// ObjectDisposedException
}