2

下面的一次性图案呢?

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

} 

更新

我的意思是说,如果没有非托管资源,我需要终结器吗?上面的一次性图案还不够好吗?是的,即使用户/开发人员不调用 dispose,GC 不默认调用 dispose 吗?

GC 调用 dispose 和 finalizers 的顺序又如何呢?

请参阅此问题以获取更多详细信息。

换句话说,当我们有终结器时,为什么我们要Dispose以 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(),它可以抑制终结器,即如果没有本地资源,我们不需要终结器。

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

2 回答 2

13

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

不过这种情况非常少见——通常你只有通过其他托管类型间接引用非托管资源,如果需要它们,它们将具有终结器。

于 2012-06-01T17:27:39.580 回答
4

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

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

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

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

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

于 2012-06-01T17:35:48.477 回答