У меня есть простой класс, который определен как ниже.
public class Person
{
public Person()
{
}
public override string ToString()
{
return "I Still Exist!";
}
~Person()
{
p = this;
}
public static Person p;
}
Основной метод
public static void Main(string[] args)
{
var x = new Person();
x = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Person.p == null);
}
Должен ли сборщик мусора быть главной ссылкой на Person.p и когда именно будет вызван деструктор?
c#
.net
garbage-collection
Паримал Радж
источник
источник
Person1
? Я вижу толькоPerson
. Последнее: см. Docs.microsoft.com/dotnet/csharp/programming-guide/…, чтобы узнать, как работают финализаторы.Person1
на самом делеPerson
, исправил опечатку.GC.Collect
вызоваОтветы:
Единственное, чего вам здесь не хватает, так это того, что компилятор продлевает время жизни вашей
x
переменной до конца метода, в котором она определена - это то, что компилятор делает - но он делает это только для сборки DEBUG.Если вы измените код так, чтобы переменная была определена в отдельном методе, она будет работать так, как вы ожидаете.
Вывод следующего кода:
И код:
Поэтому в основном ваше понимание было правильно, но вы не знаете , что подлый компилятор будет держать переменная жива до тех пор , после того, как вы назвали
GC.Collect()
- даже если вы явно установите его в нуль!Как я отмечал выше, это происходит только для сборки DEBUG - предположительно, чтобы вы могли проверять значения локальных переменных во время отладки до конца метода (но это только предположение!).
Исходный код работает должным образом для сборки выпуска, поэтому следующий код выводится
false, true
для сборки RELEASE и сборкиfalse, false
DEBUG:В качестве дополнения: обратите внимание, что если вы сделаете что-то в финализаторе для класса, который заставит ссылку на финализируемый объект быть достижимой из корня программы, то этот объект НЕ будет собираться мусором до тех пор, пока этот объект больше не будет ссылки.
Другими словами, вы можете дать объекту «отсрочку исполнения» через финализатор. Это, как правило, считается плохим дизайном!
Например, в приведенном выше коде, где мы делаем
_extendMyLifetime = this
в финализаторе, мы создаем новую ссылку на объект, так что теперь он не будет собирать мусор до тех пор, пока_extendMyLifetime
(и любая другая ссылка) больше не ссылается на него.источник