什么是循环参考破坏序列

时间:2015-02-11 09:26:45

标签: c# circular-reference

这里我声明了两种类型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();

输出显示销毁顺序与其定义顺序完全相同,我想知道为什么会这样?

2 个答案:

答案 0 :(得分:3)

终结者没有保证订单:

  

两个对象的终结器不保证以任何特定顺序运行,即使一个对象引用另一个对象。也就是说,如果对象A具有对对象B的引用并且两者都具有终结器,则当对象A的终结器开始时,对象B可能已经完成。 Object.Finalize

关键终结者除外:

  

此外,CLR在普通和关键终结器之间建立弱排序:对于同时通过垃圾收集回收的对象,在任何关键终结器之前调用所有非关键终结器。 CriticalFinalizerObject

答案 1 :(得分:1)

.NET中的垃圾收集是非确定性的(正如您在调用GC.Collect时所观察到的那样)。无论如何都无法保证最终确定的顺序。

是的,这意味着引用的对象可以在引用它们的对象之前完成。编写终结器的原因之一是非常困难的。你可能会在" deinitialized"状态。

尽量不要使用终结器。很少需要它们。