これは間違いなく発生する可能性があります。たとえば、コンストラクターの実行中にインスタンスをファイナライズできることを示すデモを次に示します。
class Program
{
private static int _lifeState;
private static bool _end;
private sealed class Schrodinger
{
private int _x;
public Schrodinger()
{
//Here I'm using 'this'
_x = 1;
//But now I no longer reference 'this'
_lifeState = 1;
//Keep busy to provide an opportunity for GC to collect me
for (int i=0;i<10000; i++)
{
var garbage = new char[20000];
}
//Did I die before I finished being constructed?
if (Interlocked.CompareExchange(ref _lifeState, 0, 1) == 2)
{
Console.WriteLine("Am I dead or alive?");
_end = true;
}
}
~Schrodinger()
{
_lifeState = 2;
}
}
static void Main(string[] args)
{
//Keep the GC churning away at finalization to demonstrate the case
Task.Factory.StartNew(() =>
{
while (!_end)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
});
//Keep constructing cats until we find the desired case
int catCount = 0;
while (!_end)
{
catCount++;
var cat = new Schrodinger();
while (_lifeState != 2)
{
Thread.Yield();
}
}
Console.WriteLine("{0} cats died in the making of this boundary case", catCount);
Console.ReadKey();
}
}
これを機能させるには、リリース ビルドを生成して Visual Studio の外部で実行する必要があります (そうしないと、デバッガーが効果を妨げるコードを挿入します)。.NET 4.0 x64 をターゲットとする VS 2010 でこれをテストしました。
'keep busy' ループの繰り返しを微調整して、Cat が完成する前に終了する確率に影響を与えることができます。