在.NET中,我应该在哪种情况下使用GC.SuppressFinalize()
?
使用这种方法有什么好处?
SuppressFinalize只能由具有终结器的类调用.它通知垃圾收集器(GC)this
完全清理了对象.
有终结器时推荐的IDisposable模式是:
public class MyClass : IDisposable { private bool disposed = false; protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // called via myClass.Dispose(). // OK to use any private object references } // Release unmanaged resources. // Set large fields to null. disposed = true; } } public void Dispose() // Implement IDisposable { Dispose(true); GC.SuppressFinalize(this); } ~MyClass() // the finalizer { Dispose(false); } }
通常,CLR在创建对象时会使用终结器对对象进行标记(使创建成本更高).SuppressFinalize告诉GC该对象已正确清理,无需进入终结器队列.它看起来像一个C++析构函数,但不会像一个人那样行事.
SuppressFinalize优化并不简单,因为您的对象可以在终结器队列上等待很长时间.不要试图在其他物体上调用SuppressFinalize.这是一个等待发生的严重缺陷.
设计指南告诉我们,如果您的对象实现了IDisposable,则不需要终结器,但如果您有终结器,则应实现IDisposable以允许确定性地清理您的类.
大多数情况下,您应该能够使用IDisposable来清理资源.当对象保留在非托管资源上并且需要保证清理这些资源时,您应该只需要一个终结器.
注意:有时编码器会添加一个终结器来调试自己的IDisposable类的构建,以便测试代码是否正确处理了它们的IDisposable对象.
public void Dispose() // Implement IDisposable { Dispose(true); #if DEBUG GC.SuppressFinalize(this); #endif } #if DEBUG ~MyClass() // the finalizer { Dispose(false); } #endif
你告诉系统,在终结器中完成的任何工作都已经完成,所以不需要调用终结器.从.NET文档:
实现IDisposable接口的对象可以从IDisposable.Dispose方法调用此方法,以防止垃圾收集器在不需要它的对象上调用Object.Finalize.
通常,大多数Dispose()方法都应该能够调用GC.SupressFinalize(),因为它应该清理在终结器中清理的所有内容.
SupressFinalize只是提供一种优化,允许系统不打扰将对象排队到终结器线程.无论是否调用GC.SupressFinalize(),正确编写的Dispose()/终结器都可以正常工作.