Eu tenho uma classe simples que é definida como abaixo.
public class Person
{
public Person()
{
}
public override string ToString()
{
return "I Still Exist!";
}
~Person()
{
p = this;
}
public static Person p;
}
No método principal
public static void Main(string[] args)
{
var x = new Person();
x = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Person.p == null);
}
O coletor de lixo deve ser a principal referência para Person.p e quando exatamente o destruidor será chamado?
c#
.net
garbage-collection
Parimal Raj
fonte
fonte
Person1
? Eu vejo apenasPerson
. Por último: consulte docs.microsoft.com/dotnet/csharp/programming-guide/… para saber como os finalizadores funcionam.Person1
éPerson
, na verdade , corrigido o erro de digitação.GC.Collect
chamadaRespostas:
O que você está perdendo aqui é que o compilador está estendendo a vida útil da sua
x
variável até o final do método em que está definida - isso é apenas algo que o compilador faz - mas apenas o faz para uma compilação DEBUG.Se você alterar o código para que a variável seja definida em um método separado, ela funcionará conforme o esperado.
A saída do seguinte código é:
E o código:
Então, basicamente, seu entendimento estava correto, mas você não sabia que o compilador furtivo manteria sua variável ativa até depois que você ligou
GC.Collect()
- mesmo que você a defina explicitamente como nula!Como observei acima, isso só acontece para uma compilação DEBUG - presumivelmente para que você possa inspecionar os valores para variáveis locais enquanto depura até o final do método (mas isso é apenas um palpite!).
O código original funciona como esperado para uma compilação de lançamento - portanto, o código a seguir gera
false, true
uma compilação RELEASE efalse, false
uma compilação DEBUG:Como um adendo: observe que, se você fizer algo no finalizador de uma classe que faça com que uma referência ao objeto que está sendo finalizado seja alcançável a partir de uma raiz do programa, esse objeto NÃO será coletado como lixo, a menos e até que esse objeto não esteja mais referenciado.
Em outras palavras, você pode dar a um objeto uma "suspensão da execução" através do finalizador. Geralmente, isso é considerado um projeto ruim!
Por exemplo, no código acima, onde fazemos
_extendMyLifetime = this
no finalizador, estamos criando uma nova referência ao objeto, para que ele não seja coletado como lixo até que_extendMyLifetime
(e qualquer outra referência) não faça mais referência a ele.fonte