在。net中,在什么情况下我应该使用GC.SuppressFinalize()?
使用这种方法给我带来了什么好处?
在。net中,在什么情况下我应该使用GC.SuppressFinalize()?
使用这种方法给我带来了什么好处?
当前回答
SuppressFinalize只能由具有终结器的类调用。它通知垃圾收集器(GC)此对象已完全清理。
当你有终结器时,推荐的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的对象的Dispose方法上调用,这样,如果有人调用Dispose方法,GC就不会再次调用终结器。
参见:GC.SuppressFinalize(对象)方法- Microsoft Docs
Dispose(true);
GC.SuppressFinalize(this);
如果对象有终结器,.net会在终结队列中放入一个引用。
因为我们已经调用Dispose(true),它清除对象,所以我们不需要结束队列来做这项工作。
因此调用GC.SuppressFinalize(this)删除终结队列中的引用。
suppressfinalize告诉系统,在终结器中已经完成的任何工作都已经完成,因此不需要调用终结器。来自。net文档:
实现IDisposable的对象 接口可以调用此方法 IDisposable。处理方法为 防止垃圾回收 调用对象。最后确定 对象,该对象不需要该对象。
一般来说,大多数Dispose()方法都应该能够调用gc . suppressfinalize(),因为它应该清除终结器中应该清除的所有内容。
SupressFinalize只是提供了一种优化,允许系统不麻烦将对象排队到终结器线程。正确编写的Dispose()/终结器应该在调用gc . suppressfinalize()或不调用gc . suppressfinalize()的情况下正常工作。
如果一个类或从类派生的任何东西可能持有对具有终结器的对象的最后一个活动引用,那么应该在任何可能受到终结器不利影响的操作之后对该对象调用GC.SuppressFinalize(this)或GC.KeepAlive(this),从而确保终结器在该操作完成之前不会运行。
GC.KeepAlive()和GC.SuppressFinalize(this)的代价在任何没有终结器的类中本质上是相同的,有终结器的类通常应该调用GC.SuppressFinalize(this),因此使用后一个函数作为Dispose()的最后一步可能并不总是必要的,但它不会是错误的。
SuppressFinalize只能由具有终结器的类调用。它通知垃圾收集器(GC)此对象已完全清理。
当你有终结器时,推荐的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