законно ли воссоздавать корневую ссылку на "this" в деструкторе .net?
-
03-07-2019 - |
Вопрос
Законно ли писать следующее в .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, если оно используется после удаления.
Сборщик мусора делит объекты на три группы:
- Те, которые все еще живы, потому что при последней проверке корневая ссылка существовала вне очереди завершения;
- Те, которые необходимо удалить, потому что нигде не существует корневой ссылки;
- Те, которые необходимо доработать, потому что корневая ссылка существует в очереди завершения, но нигде больше.