PaR*_*RaJ 9 .net c# garbage-collection
我有一个简单的类,定义如下。
public class Person
{
public Person()
{
}
public override string ToString()
{
return "I Still Exist!";
}
~Person()
{
p = this;
}
public static Person p;
}
Run Code Online (Sandbox Code Playgroud)
在主要方法中
public static void Main(string[] args)
{
var x = new Person();
x = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Person.p == null);
}
Run Code Online (Sandbox Code Playgroud)
是否应该将垃圾收集器作为Person.p的主要引用,以及何时将调用析构函数?
Mat*_*son 13
您在这里缺少的是,编译器将x变量的生存期延长到定义它的方法的末尾-这只是编译器所做的事情- 但它仅对DEBUG构建有效。
如果更改代码以使变量在单独的方法中定义,则它将按预期工作。
以下代码的输出是:
False
True
Run Code Online (Sandbox Code Playgroud)
和代码:
using System;
namespace ConsoleApp1
{
class Finalizable
{
~Finalizable()
{
_extendMyLifetime = this;
}
public static bool LifetimeExtended => _extendMyLifetime != null;
static Finalizable _extendMyLifetime;
}
class Program
{
public static void Main()
{
test();
Console.WriteLine(Finalizable.LifetimeExtended); // False.
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Finalizable.LifetimeExtended); // True.
}
static void test()
{
new Finalizable();
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,基本上您的理解是正确的,但您不知道欺骗性的编译器将在调用之前使变量保持活动状态GC.Collect()-即使您将其显式设置为null!
如上所述,这仅在DEBUG构建中发生-大概是这样,您可以在调试到方法末尾时检查局部变量的值(但这只是一个猜测!)。
原始代码确实可以在发行版本中正常工作-因此,以下代码输出false, true用于RELEASE版本和false, falseDEBUG版本:
using System;
namespace ConsoleApp1
{
class Finalizable
{
~Finalizable()
{
_extendMyLifetime = this;
}
public static bool LifetimeExtended => _extendMyLifetime != null;
static Finalizable _extendMyLifetime;
}
class Program
{
public static void Main()
{
new Finalizable();
Console.WriteLine(Finalizable.LifetimeExtended); // False.
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Finalizable.LifetimeExtended); // True iff RELEASE build.
}
}
}
Run Code Online (Sandbox Code Playgroud)
作为附录:请注意,如果您在类的终结器中执行某项操作,从而导致可以从程序根目录访问要终结的对象,则除非并且直到该对象不再存在,否则该对象将不会被垃圾回收。参考。
换句话说,您可以通过终结器为对象赋予“执行中止”。但是,通常认为这是一个不好的设计!
例如,在上面的代码中,我们_extendMyLifetime = this在终结器中所做的工作,我们正在创建对该对象的新引用,因此,在_extendMyLifetime(和任何其他引用)不再引用该对象之前,将不再对其进行垃圾收集。