在.NET中什么时候应该调用 GC.SuppressFinalize()?

咨询区

  • GEOCHET

在 .NET 中,请问哪一种情况必须要使用 GC.SuppressFinalize() 方法,它到底能给到我什么好处?.

回答区

  • Robert Paulson

SuppressFinalize() 方法只能被含有终结器方法的类使用,它通知 GC 这个 this 对象已经被手工清理了。

建议在 含有 finalizer 方法的类上使用 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);
    }
}

通常来说,如果一个含有 finalizer 方法的类被创建,那么 CLR 就会一直密切监控着它,所以它的创建相比普通的类要更加昂贵一些,而 SuppressFinalize 方法就是告诉GC,我已经清除完毕了,你不需要从 FinalizeQueue 中去提取,这就有点像 C++ 的析构函数,但本质上不是一个东西。

点评区

其实很好理解,当创建了一个带有 finalizer 方法的类,那这个类的实例地址也会在 FinalizeQueue 中存放一份,当 GC 回收该对象时,GC会将其放到 FreachableQueue 队列中,这样终结器线程就能够从这个队列中提取,进而执行对象的 finalizer 方法,可以参考下面的代码:

namespace ConsoleApp5
{
    class Program
    {
        static void Main(string[] args)
        {
            Run();
            GC.Collect();
            Console.ReadLine();
        }

        static void Run()
        {
            var person = new Person();
            Console.WriteLine("person 已实例化!");
        }
    }

    class Person
    {
        ~Person()
        {
            Console.WriteLine("我是析构函数!");
            Console.ReadLine();
        }
    }
}

在.NET中什么时候应该调用 GC.SuppressFinalize()?

 

接下来问题来了,我能不能不要让 终结器线程 来执行我的析构函数呢?这就需要用 SuppressFinalize() 方法来抑制了,修改 Run 方法如下:

static void Run()
{
   var person = new Person();
   Console.WriteLine("person 已实例化!");
   GC.SuppressFinalize(person);
}

在.NET中什么时候应该调用 GC.SuppressFinalize()?

 

可以看到,这回 终结器线程 没有执行我的析构函数了,就这么简单,如果有朋友对细节感兴趣,有机会用 windbg 让大家眼见为实。