законно ли воссоздавать корневую ссылку на «это» в деструкторе .net? - PullRequest
4 голосов
/ 03 марта 2009

Законно ли писать следующее в .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();
    }

Он работает и записывает '0' в консоль, как и ожидалось, но мне интересно, гарантированно ли она всегда работает.

Кто-то знает, что происходит за сценой?

Ответы [ 3 ]

8 голосов
/ 03 марта 2009

Это называется воскресением, и это законно. Google для ". Воскресение объекта" (и такие термины, как это), и вы найдете такие вещи, как:

Воскресение и сборщик мусора .NET

Воскресение объекта

Просто убедитесь, что эти зомби-объекты не возвращаются, и попытайтесь съесть свой мозг или что-то в этом роде. Как и все некроманты, это опасные вещи. (Главным образом потому, что финализаторы выше в иерархии классов могут освободить некоторый существенный ресурс. Также обратите внимание, что финализатор не будет запущен во второй раз, если объект становится «не связанным», если вы не вызовете GC.ReRegisterForFinalize.)

1 голос
/ 03 марта 2009

Это работает, потому что первая сборка мусора не собирает экземпляр. Он просто планирует запуск финализатора для экземпляра. Затем финализатор создает новый корень для экземпляра, поэтому, когда происходит следующая коллекция, экземпляр фактически укореняется и, следовательно, не собирается для сбора.

Вы должны быть очень осторожны с этим жестом. Если финализатор используется для того, чтобы убедиться, что объект удален, это фактически нарушает протокол, потому что одноразовые шаблоны говорят, что удаленный экземпляр должен генерировать исключение ObjectDisposedException, если он используется после удаления.

0 голосов
/ 02 декабря 2010

Сборщик мусора делит объекты на три группы:

  1. Те, которые еще живы, потому что, наконец, проверьте корневую ссылку, существующую вне очереди завершения;
  2. Те, которые должны быть удалены, потому что нет рутированных ссылка существует где угодно;
  3. Те, которые должны быть завершены, потому что корневая ссылка существует в очереди завершения, но больше нигде.
Объекты не могут быть удалены, если нигде нет корневой ссылки. Завершение - это отдельный этап перед удалением; обратите внимание, что хотя объект зарегистрирован для завершения, все объекты, на которые он ссылается прямо или косвенно, будут защищены от удаления, но не от завершения.
...