Question

Est-il légal d'écrire ce qui suit 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();
    }

Cela fonctionne et écrit «0» sur la console comme prévu, mais je me demande s’il est garanti que cela fonctionnera toujours.

Est-ce que quelqu'un sait ce qui se passe derrière la scène?

Était-ce utile?

La solution

C'est ce qu'on appelle la résurrection, et c'est légal. Google pour ".net la résurrection d'objet" " (et des termes similaires) et vous trouverez des informations telles que:

La résurrection d'objet

Assurez-vous simplement que ces objets zombies ne reviennent pas et tentent de manger votre cerveau ou quelque chose du genre. Comme toute nécromancie, c'est dangereux. (Principalement parce que les finaliseurs plus haut dans la hiérarchie des classes peuvent avoir libéré des ressources essentielles. Notez également que le finaliseur ne sera pas exécuté une seconde fois si l'objet devient "non référencé", sauf si vous appelez GC.ReRegisterForFinalize .)

Autres conseils

Cela fonctionne car la première collecte de place ne collecte pas l'instance. Il planifie simplement l'instance pour que son finaliseur soit exécuté. Le finaliseur crée ensuite une nouvelle racine pour l'instance. Ainsi, lors de la prochaine collecte, l'instance est réellement enracinée et ne peut donc pas être collectée.

Vous devriez être très prudent avec ce dur. Si le finaliseur est utilisé pour s'assurer qu'un objet est supprimé, cela enfreint le protocole car les modèles jetables indiquent qu'une instance supprimée doit émettre une exception ObjectDisposedException si elle est utilisée après avoir été supprimée.

Le ramasse-miettes divise les objets en trois groupes:

  1. Ceux qui sont toujours en vie, car il a été vérifié qu'une référence enracinée existait en dehors de la file d'attente de finalisation;
  2. doivent être supprimés, car aucune référence enracinée n'existe nulle part;
  3. Ceux qui doivent être finalisés, car une référence enracinée existe dans la file d'attente de finalisation, mais nulle part ailleurs.
Les objets ne peuvent être supprimés que s'il n'y a pas de référence enracinée nulle part. La finalisation est une étape distincte avant la suppression; Notez que lorsqu'un objet est enregistré pour la finalisation, tous les objets qu'il référence directement ou indirectement seront protégés contre la suppression, mais pas contre la finalisation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top