为什么在终结器中序列化对象不是一个好主意?

Hoh*_*eim 5 c# finalizer

在Headfirst C#一书中,我认为"在终结器中序列化一个对象并不是一个好主意,因为序列化需要整个对象树在堆中,但是你可能最终缺少重要部分你的程序是因为在终结器运行之前可能已经收集了一些对象."

我的问题是,由于我的对象获得了对其他对象的引用(这意味着至少有一个对其他对象的引用),在终结器运行之前它们如何被垃圾收集?

Mic*_*eld 9

因为垃圾收集器没有定义运行终结器的任何顺序,并且不关心您的对象是否按顺序完成.

当终结器运行时,GC已经确定它和它引用的每个对象都是无法访问的,因此所有这些子对象也将被收集.这些对象中的每一个都被添加到终结器队列中,但不能保证 GC将以任何外向敏感的顺序处理它们.

这是你在终结器中可以做的限制之一:你必须假设你的所有子对象都已经被破坏了.Object.Finalize的文档明确地调用它:

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


Tho*_*que 8

终结器的问题在于它们提供的保证非常少:

  • 他们不能保证永远不会跑
  • 你无法预测何时他们将运行
  • 当它们运行时,它们引用的某些对象可能已经完成,因此您的对象可能不处于有效状态

Eric Lippert有两篇关于此的博文:

在任何情况下,99%你曾经写过的课程可能根本就没有终结者.极少数情况下他们确实是必要的.如果您在使用完对象后需要执行清理,请IDisposable改为实现,至少您可以以确定的方式进行控制.