在.NET中,我应在哪种情况下使用GC.SuppressFinalize()
?
使用此方法有什么优点?
在.NET中,我应在哪种情况下使用GC.SuppressFinalize()
?
使用此方法有什么优点?
Answers:
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
IDisposable
不是sealed
,则GC.SuppressFinalize(this)
即使它不包括用户定义的finalizer,它也应包括对的调用。这对于确保添加了用户定义的终结器但仅覆盖受保护的Dispose(bool)
方法的派生类型具有适当的语义是必要的。
sealed
通过@SamHarwell提到的是非常重要的,派生类。当类未密封时,CodeAnalysis会生成ca1816 + ca1063,但没有时,密封类很好SuppressFinalize
。
SupressFinalize
告诉系统在终结器中将完成的所有工作都已经完成,因此不需要调用终结器。从.NET文档:
实现IDisposable接口的对象可以从IDisposable.Dispose方法调用此方法,以防止垃圾回收器在不需要它的对象上调用Object.Finalize。
通常,大多数任何Dispose()
方法都应该能够调用GC.SupressFinalize()
,因为它应该清除将在终结器中清除的所有内容。
SupressFinalize
只是提供了一种优化,使系统不必费心将对象排队到终结器线程。编写正确的Dispose()
/ finalizer应该在调用或不调用的情况下正常工作GC.SupressFinalize()
。
必须在Dispose
实现的对象的方法上调用该方法,IDisposable
这样,如果有人调用该Dispose
方法,GC将不会再次调用终结器。