首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么时候应该使用GC.SuppressFinalize()?

什么时候应该使用GC.SuppressFinalize()?
EN

Stack Overflow用户
提问于 2008-09-29 22:41:40
回答 5查看 130.5K关注 0票数 339

在.NET中,在什么情况下应该使用GC.SuppressFinalize()

使用此方法有什么好处?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2008-09-29 23:56:04

SuppressFinalize只能由具有终结器的类调用。它通知垃圾收集器(GC) this对象已被完全清除。

当您有终结器时,推荐的IDisposable模式是:

代码语言:javascript
复制
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对象。

代码语言:javascript
复制
public void Dispose() // Implement IDisposable
{
    Dispose(true);
#if DEBUG
    GC.SuppressFinalize(this);
#endif
}

#if DEBUG
~MyClass() // the finalizer
{
    Dispose(false);
}
#endif
票数 343
EN

Stack Overflow用户

发布于 2008-09-29 22:44:22

SupressFinalize告诉系统,在终结器中完成的所有工作都已经完成,因此不需要调用终结器。从.NET文档中:

实现IDisposable接口的

对象可以从IDisposable.Dispose方法调用此方法,以防止垃圾回收器对不需要此方法的对象调用Object.Finalize。

一般来说,几乎任何Dispose()方法都应该能够调用GC.SupressFinalize(),因为它应该清理终结器中要清除的所有内容。

SupressFinalize只是提供了一种优化,允许系统不必费心将对象排队到终结器线程。无论是否调用GC.SupressFinalize(),正确编写的Dispose()/finalizer都应该正常工作。

票数 43
EN

Stack Overflow用户

发布于 2018-04-16 09:54:03

代码语言:javascript
复制
Dispose(true);
GC.SuppressFinalize(this);

如果对象有终结器,.net会将一个引用放入终结器队列中。

因为我们已经调用了Dispose(true),它清除了对象,所以我们不需要finalization队列来完成这项工作。

因此调用GC.SuppressFinalize(this) remove reference in finalization队列。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/151051

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档