如果我的类实现了 IDisposable,为什么我需要终结器

本文关键字:为什么 我的 实现 IDisposable 如果 | 更新日期: 2023-09-27 18:35:59

那么下面的一次性模式呢?

using System;
public class MyClass : IDisposable 
{     
    public void Dispose() 
        // Implement IDisposable     
    {
        //just do the cleanup
        GC.SuppressFinalize(this);
    } 
} 

更新

我的意思是说,如果没有非托管资源,我需要终结器吗?上面的一次性模式还不够好吗?是的,即使用户/开发人员不调用释放,GC 调用默认情况下也不会释放吗?

那么 GC 调用释放器和终结器的顺序呢?

有关更多详细信息,请参阅此问题。

换句话说,当我们有终结器时,为什么我们调用 false 作为参数的 Dispose


从 http://msdn.microsoft.com/en-us/magazine/cc163392.aspx#S2 来看,似乎始终建议从终结器而不是托管引用中释放非托管资源。

始终建议从 Dispose 方法释放非托管资源。阅读这篇文章时,我仍然没有得到全部要点。

但是,如果没有非托管资源,则以下模式应该有效。


根据 msdn.microsoft.com/en-us/magazine/cc163392.aspx#S2 的说法,msdn.microsoft.com/en-us/library/fs2xkftw.aspx 建议在终结器中释放本机资源,并且所有资源都使用 dispose()。如果显式调用dispose(),它可以抑制终结器,即如果没有本机资源,我们不需要终结器。

using System;
public class MyClass : IDisposable 
{ 
    private bool disposed = false;  
    protected virtual void Dispose(bool suppressFinalize) 
    {    
        if (!disposed)
        {
            //Just do the cleanup
            //and release resources
            disposed = true; 
        }
        if (!suppressFinalize)
        {
            GC.SuppressFinalize(this); 
        }
    }
    public void Dispose() 
        // Implement IDisposable     
    {
        Dispose(true);           
    } 
    ~MyClass() // the finalizer
    {     
        Dispose(false);    
    }
} 

如果我的类实现了 IDisposable,为什么我需要终结器

因为您可能直接引用了非托管资源(例如 Windows 句柄),并且即使没有人调用 Dispose,您也希望释放它们。

不过,这种情况非常罕见 - 通常您实际上只能通过其他托管类型间接引用非托管资源,这些托管类型在需要时将具有终结器。

> .Net 中的 Finalization + IDisposable 实际上是两个不同的问题,试图用单一的一次性模式来解决。

  • 托管资源清理
  • 非托管资源清理

非托管资源是不受 CLR 和垃圾回收器控制的项目。 诸如文件句柄,从PInvoke返回的内存等项目... 如果用户代码未显式释放这些资源,它们将泄漏并在进程生存期的剩余时间内存在。 释放他们至关重要。

这就是终结器的用武之地。 它将在 CLR 收集对象之前在对象上运行。 这不需要使用者遵循一次性模式,因此是确保释放非托管资源以防止泄漏的良好后备。

如果代码不包含任何直接持有的非托管资源,则没有理由使用终结器。 保存非托管资源的代码负责拥有终结器。