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

时间:2012-06-01 17:25:56

标签: c# .net c#-3.0

下面的一次性图案怎么样?

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

} 

对不起,请注意。我想说,如果没有未管理的资源,我需要终结器吗?上述一次性图案不够好吗?是的,即使用户/开发者没有调用dispose,默认情况下GC不会调用处理吗?

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

请看 standard dispose pattern? why do we need "disposing" parameter in the virtual method and isn't the finalizer get called after dipose always?  了解更多详情。

另外,当我们有终结器时,为什么我们调用Dispose with false作为参数。


来自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()被明确地调用,它可以抑制finalizer.i.e;如果没有原生的reosurces,我们不需要fianlizer。

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);    
    }
} 

的问候, 梦

2 个答案:

答案 0 :(得分:11)

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

这是非常罕见的 - 通常你只有真的通过其他托管类型间接引用非托管资源,如果需要它们将有终结器。

答案 1 :(得分:4)

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

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

非托管资源是不受CLR和垃圾收集器控制的项目。文件句柄,从PInvoke返回的内存等项目......如果这些资源没有被用户代码明确释放,它们将泄漏并在剩余的进程生命周期中出现。他们被释放至关重要。

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

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

相关问题