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

时间:2015-08-29 12:19:11

标签: c# finalizer

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

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

2 个答案:

答案 0 :(得分:9)

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

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

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

  

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

答案 1 :(得分:8)

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

  • 他们无法保证能够继续
  • 您无法预测何时运行
  • 当它们运行时,它们引用的某些对象可能已经完成,因此您的对象可能未处于有效状态

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

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