Esto sin duda puede ocurrir. Por ejemplo, aquí es una demostración de que una instancia puede ser finalizado mientras se está ejecutando su constructor:
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();
}
}
Para que esto funcione, es necesario emitir una versión de lanzamiento y ejecutar fuera de Visual Studio (como se de lo contrario, el depurador inserta un código que previene el efecto). He probado esto con VS 2010 que apunta a .NET 4.0 x64.
Puede ajustar las iteraciones en el ciclo 'keep busy' (mantener ocupado) para impactar la probabilidad de que el final del Cat finalice antes de su construcción completa.
Voy a esperar a que Eric Lippert pase por aquí y se ocupe de esto ... –
@StefanH, creo que he visto una respuesta de Eric sobre una pregunta muy similar a esta (o una entrada de blog de él) pero mi google-fu está fallando en este momento = ( – Rob
@Rob - Lo sé! Intenté simplemente buscar en Google "C# Garbage Collection" porque supuse que sería el primer resultado. –