¿Es legal recrear una referencia enraizada a 'esto' en un destructor .net?
-
03-07-2019 - |
Pregunta
¿Es legal escribir lo siguiente en .net?
public class A
{
public int i = 0;
~A()
{
Aref = this;
}
}
public static A Aref;
static void Main(string[] args)
{
Aref = new A();
int gen = GC.GetGeneration(Aref);
Aref = null;
GC.Collect(gen, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
Console.WriteLine(Aref.i);
Console.ReadLine();
}
Funciona y escribe '0' en la consola como se esperaba, pero me pregunto si está garantizado que siempre funcionará.
¿Alguien sabe lo que está sucediendo detrás de la escena?
Solución
Se llama resurrección, y es legal. Google para " .net object resurrection " (y términos similares) y encontrarás cosas como:
Solo asegúrate de que estos objetos zombies no vuelvan y trata de comerte el cerebro o algo así. Como toda nigromancia, esto es algo peligroso. (Principalmente porque los finalizadores más altos en la jerarquía de clases pueden haber liberado algún recurso esencial. También tenga en cuenta que el finalizador no se ejecutará una segunda vez si el objeto no se hace referencia a él, a menos que llame a GC.ReRegisterForFinalize .)
Otros consejos
Funciona porque la primera recolección de basura no recopila la instancia. Simplemente programa la instancia para que se ejecute su finalizador. Luego, el finalizador crea una nueva raíz para la instancia, de modo que, cuando se produce la próxima recopilación, la instancia está realmente enraizada y, por lo tanto, no está lista para su recopilación.
Debes tener mucho cuidado con esto duro. Si el finalizador se usa para asegurarse de que se elimine un objeto, esto viola el protocolo porque los patrones desechables dicen que una instancia dispuesta debería lanzar una ObjectDisposedException si se usa después de desecharse.
El recolector de basura divide los objetos en tres grupos:
- Aquellos que aún están vivos, porque al final se comprueba que una referencia arraigada existe fuera de la cola de finalización;
- Aquellos que debe eliminarse, porque no existe ninguna referencia enraizada en ninguna parte;
- Las que necesitan finalizarse, porque existe una referencia enraizada en la cola de finalización, pero en ninguna otra parte.