终结者和IDisposable

根据文档(MSDN: 链接 ),很明显在实现终结器时应该使用IDisposable模式。

但是,如果实现IDisposable(以便提供处理对象的确定性方法),您是否需要实现终结器?并且您没有任何非托管资源来清理?

在我看来,如果类只有托管资源,如果你不调用Dispose,那么托管资源将自动被GC清理,因此不需要实现终结器。 我错了吗?

另外,如果我使用我的Dispose方法清理事件处理程序,该怎么办? 由于Dispose不会自动被GC调用,我应该实现Finalizer,以确保事件处理程序无线连接吗?

不,如果您有一个实现IDisposable的类(即如果您已正确实现模式,并且您只有托管资源可以处置),则不需要实现终结器。

(如果这样做,它实际上会影响对象的生命周期,因为带有终结器的对象会被添加到GC中的终结队列中,并且可以比他们需要的时间更长 – 如果对象很大,这可能是个问题。)

除非您拥有非托管资源,否则不应添加终结器。

拥有托管可支配资源但不拥有非托管资源的类应实现完整的Dispose模式,但不具有终结器。

如果该类未被sealed ,则应在其Dispose()方法中调用GC.SuppressFinalize(this) ,以防inheritance的类添加终结器。

  1. 不,你是对的,如果你的对象持有一个拥有非托管资源的对象,那么你应该实现IDisposable,这样你就可以在你的Dispose上调用它的Dispose,但你不需要终结者,因为它的终结者会处理这个问题。

  2. 事实上,尝试与终结者中的最终成员做任何事情是充实的,因为终结者将执行的命令不是确定性的,所以如果你试图这样做,你可以得到一些讨厌的错误。

  3. 通常,让一个类保存1个或0个非托管资源要好得多。 如果它有1个非托管资源,它应该具有处理它所需的其他状态(即没有其他可支配成员)。 SafeHandle是解决这个问题的好方法。 如果一个类需要处理几个非托管资源,它应该通过这些处理程序类处理所述资源来实现。 然后终结者和IDisposable变得容易; 要么你有唯一的非托管资源来处理(如果调用dispose则取消终结者)或者你只需​​要IDisposable。

因为必须直接处理非托管资源是相对罕见的,所以你很可能永远不必编写终结者(我想我曾经在实际代码中这样做了一次)。 因为敏感的人在处理非托管资源的类中没有做太多其他事情,所以整个Dispose(bool)事情也是不必要的。

如果您只拥有托管资源,则根本不需要实现IDisposable。 IDisposable用于清除GC域之外的东西,例如本机句柄,数据库连接等。

如果您的控件包含实现IDisposable的控件并且它们必须释放本机资源,那么您仍然需要实现IDisposable模式并为您的子控件提供处置机会。

在终结器中调用Dispose()的原因是作为最后的手段,如果对象没有正确处理,GC将作为最后的努力。

是的,如果您只有托管资源,那么当垃圾收集发生时,GC将清理它们(并且没有任何生命引用指向它们)

但在这种情况下,为什么需要在类型上实现IDisposable? 我的意思是,你似乎认为在你的情况下,不处理你的对象不是一个大问题,那么为什么有人会处置它们呢?

您还应该注意到使用Finalizer时存在垃圾收集的性能问题:任何带有终结器的对象都将逃脱第一次GC传递,如果这些对象是短暂的,这将大大降低GC效率。

在第一次垃圾收集期间,应该清理对象,但不会执行终结器。 然后,该对象将被认为是GC的长寿命,即使它已经被清除了。

我从来没有需要实现终结器。 如您所知,它使对象有机会在GC之前做任何需要的事情。 应该在dispose方法中释放所有资源