C# 我什么时候应该使用 GC.SuppressFinalize()?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/151051/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When should I use GC.SuppressFinalize()?
提问by Sam Saffron
In .NET, under which circumstances should I use GC.SuppressFinalize()
?
在 .NET 中,我应该在什么情况下使用GC.SuppressFinalize()
?
What advantage(s) does using this method give me?
使用这种方法给我带来什么好处?
采纳答案by Robert Paulson
SuppressFinalize should only be called by a class that has a finalizer. It's informing the Garbage Collector (GC) that this
object was cleaned up fully.
SuppressFinalize 只能由具有终结器的类调用。它通知垃圾收集器 (GC)this
对象已完全清除。
The recommended IDisposable pattern when you have a finalizer is:
当您有终结器时,推荐的 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);
}
}
Normally, the CLR keeps tabs on objects with a finalizer when they are created (making them more expensive to create). SuppressFinalize tells the GC that the object was cleaned up properly and doesn't need to go onto the finalizer queue. It looks like a C++ destructor, but doesn't act anything like one.
通常,在创建对象时,CLR 会使用终结器密切关注对象(使创建它们的成本更高)。SuppressFinalize 告诉 GC 对象已正确清理,不需要进入终结器队列。它看起来像一个 C++ 析构函数,但不像一个析构函数。
The SuppressFinalize optimization is not trivial, as your objects can live a long time waiting on the finalizer queue. Don't be tempted to call SuppressFinalize on other objects mind you. That's a serious defect waiting to happen.
SuppressFinalize 优化并不简单,因为您的对象可以在终结器队列中等待很长时间。不要试图在其他对象上调用 SuppressFinalize。这是一个等待发生的严重缺陷。
Design guidelines inform us that a finalizer isn't necessary if your object implements IDisposable, but if you have a finalizer you should implement IDisposable to allow deterministic cleanup of your class.
设计指南告诉我们,如果您的对象实现 IDisposable,则不需要终结器,但如果您有终结器,则应该实现 IDisposable 以允许对您的类进行确定性清理。
Most of the time you should be able to get away with IDisposable to clean up resources. You should only need a finalizer when your object holds onto unmanaged resources and you need to guarantee those resources are cleaned up.
大多数情况下,您应该可以使用 IDisposable 来清理资源。当您的对象持有非托管资源并且您需要保证这些资源被清理时,您应该只需要一个终结器。
Note: Sometimes coders will add a finalizer to debug builds of their own IDisposable classes in order to test that code has disposed their IDisposable object properly.
注意:有时编码人员会添加一个终结器来调试他们自己的 IDisposable 类的构建,以测试代码是否正确处理了他们的 IDisposable 对象。
public void Dispose() // Implement IDisposable
{
Dispose(true);
#if DEBUG
GC.SuppressFinalize(this);
#endif
}
#if DEBUG
~MyClass() // the finalizer
{
Dispose(false);
}
#endif
回答by albertein
That method must be called on the Dispose method of objects that implements the IDisposable, in this way the GC wouldn't call the finalizer another time if someones calls the Dispose method.
必须在实现 IDisposable 的对象的 Dispose 方法上调用该方法,这样如果有人调用 Dispose 方法,GC 将不会再次调用终结器。
See: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx
请参阅:http: //msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx
回答by Michael Burr
you're telling the system that whatever work would have been done in the finalizer has already been done, so the finalizer doesn't need to be called. From the .NET docs:
您是在告诉系统在终结器中完成的任何工作都已经完成,因此不需要调用终结器。来自 .NET 文档:
Objects that implement the IDisposable interface can call this method from the IDisposable.Dispose method to prevent the garbage collector from calling Object.Finalize on an object that does not require it.
实现 IDisposable 接口的对象可以从 IDisposable.Dispose 方法调用此方法,以防止垃圾收集器对不需要它的对象调用 Object.Finalize。
In general, most any Dispose() method should be able to call GC.SupressFinalize(), because it should clean up everything that would be cleand up in the finalizer.
一般来说,大多数 Dispose() 方法都应该能够调用 GC.SupressFinalize(),因为它应该清理将在终结器中清理的所有内容。
SupressFinalize is just something that provides an optimization that allows the system to not bother queing the object to the finalizer thread. A properly written Dispose()/finalizer should work properly with or without a call to GC.SupressFinalize().
SupressFinalize 只是提供了一种优化,允许系统不必费心将对象排队到终结器线程。正确编写的 Dispose()/finalizer 应该在调用或不调用 GC.SupressFinalize() 的情况下正常工作。
回答by Max CHien
Dispose(true);
GC.SuppressFinalize(this);
If object has finalizer, .net put a reference in finalization queue
如果对象有终结器,.net 将引用放入终结队列
Since we have call Dispose(ture), it clear object, so we don't need finalization queue to do this job.
由于我们调用了 Dispose(ture),它会清除对象,因此我们不需要终结队列来完成这项工作。
So call GC.SuppressFinalize(this) remove reference in finalization queue.
所以调用 GC.SuppressFinalize(this) 删除终结队列中的引用。
回答by supercat
If a class, or anything derived from it, might hold the last live reference to an object with a finalizer, then either GC.SuppressFinalize(this)
or GC.KeepAlive(this)
should be called on the object after any operation that might be adversely affected by that finalizer, thus ensuring that the finalizer won't run until after that operation is complete.
如果一个类或从它派生的任何东西可能持有对具有终结器的对象的最后一个实时引用,那么在任何可能受到终结器不利影响的操作之后,要么GC.SuppressFinalize(this)
或GC.KeepAlive(this)
应该在该对象上调用该对象,从而确保终结器获胜直到该操作完成后才运行。
The cost of GC.KeepAlive()
and GC.SuppressFinalize(this)
are essentially the same in any class that doesn't have a finalizer, and classes that do have finalizers should generally call GC.SuppressFinalize(this)
, so using the latter function as the last step of Dispose()
may not always be necessary, but it won't be wrong.
成本GC.KeepAlive()
和GC.SuppressFinalize(this)
基本上在任何类没有终结相同的,那确实有终结通常应该叫类GC.SuppressFinalize(this)
,因此,使用后者的功能的最后一步Dispose()
可能并不总是必要的,但它不会是错的。