законно ли воссоздавать корневую ссылку на "this" в деструкторе .net?

StackOverflow https://stackoverflow.com/questions/606595

Вопрос

Законно ли писать следующее в .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' на консоль, как и ожидалось, но мне интересно, гарантированно ли это всегда будет работать.

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

Это было полезно?

Решение

Это называется воскрешением, и это законно.Загуглите "воскрешение .net-объекта" (и подобные ему термины), и вы найдете такие вещи, как:

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

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

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

Другие советы

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top