Domanda

È legale scrivere quanto segue in .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();
    }

Funziona e scrive '0' sulla console come previsto, ma mi chiedo se è garantito che funzioni sempre.

Qualcuno sa cosa sta succedendo dietro la scena?

È stato utile?

Soluzione

Si chiama resurrezione ed è legale. Google per " .net object resurrection " (e termini simili) e troverai cose come:

Resurrection oggetto

Assicurati solo che questi oggetti zombi non ritornino e cerca di divorare il tuo cervello o qualcosa del genere. Come tutta la negromanzia, questa è roba pericolosa. (Soprattutto perché i finalizzatori più in alto nella gerarchia delle classi possono aver rilasciato alcune risorse essenziali. Nota anche che il finalizzatore non verrà eseguito una seconda volta se l'oggetto viene "non referenziato", a meno che tu non chiami GC.ReRegisterForFinalize ).

Altri suggerimenti

Funziona perché la prima garbage collection non raccoglie l'istanza. Pianifica semplicemente l'istanza per l'esecuzione del finalizzatore. Il finalizzatore crea quindi una nuova radice per l'istanza, quindi quando si verifica la raccolta successiva l'istanza è effettivamente radicata e quindi non può essere raccolta.

Dovresti stare molto attento con questo duro. Se il finalizzatore viene utilizzato per assicurarsi che un oggetto sia eliminato, questo in realtà viola il protocollo poiché i modelli usa e getta indicano che un'istanza eliminata dovrebbe generare un ObjectDisposedException se viene utilizzata dopo essere stata eliminata.

Il garbage collector divide gli oggetti in tre gruppi:

  1. Quelli che sono ancora vivi, perché finalmente un controllo radicato esisteva al di fuori della coda di finalizzazione;
  2. Quelli che devono essere eliminati, poiché non esiste alcun riferimento rootato da nessuna parte;
  3. Quelli che devono essere finalizzati, poiché esiste un riferimento root nella coda di finalizzazione, ma in nessun altro luogo.
Gli oggetti non possono essere eliminati a meno che non ci siano riferimenti rootati da nessuna parte. La finalizzazione è una fase distinta prima della cancellazione; notare che mentre un oggetto è registrato per la finalizzazione, tutti gli oggetti a cui fa riferimento direttamente o indirettamente saranno protetti dalla cancellazione, ma non dalla finalizzazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top