在Headfirst C#一书中,我认为“在终结器中序列化对象并不是一个好主意,因为序列化需要整个对象树在堆中,但最终可能会丢失程序的重要部分,因为在终结器运行之前可能已经收集了一些对象。“
我的问题是,由于我的对象获得了对其他对象的引用(这意味着至少有一个对其他对象的引用),在终结器运行之前它们如何被垃圾收集?
答案 0 :(得分:9)
因为垃圾收集器没有定义任何正在运行的终结器的顺序,并且不关心你的对象是否无序完成。
当你的终结器运行时,GC已经确定它和它引用的每个对象都是无法访问的,因此所有这些子对象也将被收集。这些对象中的每一个都被添加到终结器队列中,但是无保证 GC将以任何外观合理的顺序处理它们。
这是你在终结器中可以做的限制之一:你必须假设你的所有子对象都已经被破坏了。 Object.Finalize的文档明确指出了这一点:
两个对象的终结器不保证以任何特定顺序运行,即使一个对象引用另一个对象。也就是说,如果对象A具有对对象B的引用并且都具有终结器,则当对象A的终结器开始时,对象B可能已经完成。
答案 1 :(得分:8)
终结器的问题在于它们提供的保证很少:
Eric Lippert有两篇关于此的博文:
在任何情况下,99%你曾经写过的课程都可能根本没有终结者。很少有他们真正需要的情况。如果您在使用对象完成后需要执行清理,请改为实现Laravel
,至少您可以以确定的方式进行控制。