var b = new B();
var a = new A();
a.B = b;
b.A = a;
a = null;
b = null;
GC.Collect();
输出显示销毁顺序与其定义顺序完全相同,我想知道为什么会这样?
这里我声明了两种类型A和B,它们彼此引用
public class A
{
public B B { get; set; }
~A()
{
Console.WriteLine( "destructing A..." );
}
}
public class B
{
public A A { get; set; }
~B()
{
Console.WriteLine( "destructing B..." );
}
}
var b = new B();
var a = new A();
a.B = b;
b.A = a;
a = null;
b = null;
GC.Collect();
输出显示销毁顺序与其定义顺序完全相同,我想知道为什么会这样?
答案 0 :(得分:3)
终结者没有保证订单:
两个对象的终结器不保证以任何特定顺序运行,即使一个对象引用另一个对象。也就是说,如果对象A具有对对象B的引用并且两者都具有终结器,则当对象A的终结器开始时,对象B可能已经完成。 Object.Finalize
关键终结者除外:
此外,CLR在普通和关键终结器之间建立弱排序:对于同时通过垃圾收集回收的对象,在任何关键终结器之前调用所有非关键终结器。 CriticalFinalizerObject
答案 1 :(得分:1)
.NET中的垃圾收集是非确定性的(正如您在调用GC.Collect时所观察到的那样)。无论如何都无法保证最终确定的顺序。
是的,这意味着引用的对象可以在引用它们的对象之前完成。编写终结器的原因之一是非常困难的。你可能会在" deinitialized"状态。
尽量不要使用终结器。很少需要它们。