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?

¿Fue útil?

Solución

Se llama resurrección, y es legal. Google para " .net object resurrection " (y términos similares) y encontrarás cosas como:

Resurrección de objetos

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:

  1. Aquellos que aún están vivos, porque al final se comprueba que una referencia arraigada existe fuera de la cola de finalización;
  2. Aquellos que debe eliminarse, porque no existe ninguna referencia enraizada en ninguna parte;
  3. Las que necesitan finalizarse, porque existe una referencia enraizada en la cola de finalización, pero en ninguna otra parte.
Los objetos no se pueden eliminar a menos que no haya una referencia enraizada en ninguna parte. La finalización es una etapa distinta antes de la eliminación; tenga en cuenta que mientras un objeto está registrado para su finalización, todos los objetos a los que hace referencia directa o indirectamente estarán protegidos contra la eliminación, pero no contra la finalización.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top