为什么垃圾收集器以错误的顺序获取对象?

Ign*_*cia 6 c# garbage-collection destructor

我有一个带有两个类A和B的应用程序.类A有一个对类B的引用.类的析构函数执行一些资源清理,但它们必须按正确的顺序调用,首先是A的析构函数和那么B的析构函数

发生的事情是,以某种方式首先调用B的析构函数,然后A的析构函数崩溃,因为它试图从已处置的对象执行方法.

GC的这种行为是否正确?我希望GC检测到A有对B的引用,然后先调用A析构函数.我对吗?

谢谢伙伴们!

PD:如果对析构函数/终结器/处理器等有疑问,那就是我们所拥有的:

~A()
{
    this.Dispose();
}

~B()
{
    this.Dispose();
}    
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 14

正如其他人所说,你的终结者是错误的,错误的,错误的.你不能简单地在终结器中调用Dispose并期望好事发生.阅读实施一次性模式的正确方法.

做到这一点是你必须做的工作的开始,而不是结束.除了这里所有其他正确的答案,我注意到:

  • 终结器可以(通常也可以)在不同的线程上运行.最终确定与特定线程具有亲缘关系的资源是危险的,如果不小心,可能会遇到死锁,等等.

  • finalization可以通过将对它的引用分配给活动对象中的变量来"复活"死对象.不要那样做.令人难以置信的令人困惑.

  • 终结器可以在发生线程中止异常时部分构造的对象上运行.您不能假设任何对于完全构造的对象都是正确的不变量对于正在最终确定的对象都是正确的.

出于所有这些原因,正确编写终结器非常困难.避免,避免,避免.


Dom*_*nic 13

GC是不确定的:它不能保证以任何特定顺序,或在任何时间,甚至永远垃圾收集您的对象 - 如果它想要,它可以决定在程序完成后保留它们.因此,终结器很少使用或使用.

如果您想要确定性的最终化,则应使用该IDisposable模式.


Wis*_*yEh 9

来自http://msdn.microsoft.com/en-us/magazine/bb985010.aspx:

运行时不会对调用Finalize方法的顺序做出任何保证.例如,假设有一个对象包含指向内部对象的指针.垃圾收集器检测到两个对象都是垃圾.此外,假设首先调用内部对象的Finalize方法.现在,允许外部对象的Finalize方法访问内部对象并在其上调用方法,但内部对象已经完成,结果可能是不可预测的.因此,强烈建议Finalize方法不要访问任何内部成员对象.