Dispose()用于清理托管资源?

时间:2013-05-17 05:20:19

标签: c# dispose finalize

this answer我找到了,

  

清理Finalize方法中的非托管资源   Dispose方法中的托管方法,当Dispose / Finalize模式时   已在您的代码中使用。

后来我发现this nice article关于敲定和处理并清楚地了解它们。本文包含以下代码(第3页),以解释这些概念:

class Test : IDisposable
{
    private bool isDisposed = false;

    ~Test()
    {
       Dispose(false);
    }

    protected void Dispose(bool disposing)
    {
       if (disposing)
       {
          // Code to dispose the managed resources of the class
       }
       // Code to dispose the un-managed resources of the class

       isDisposed = true;
    }

    public void Dispose()
    {
       Dispose(true);
       GC.SuppressFinalize(this);
    }
}

但在此之下,会出现相同的注释(我在此问题的开头包含该注释)。

  

Dispose / Finalize Pattern     Microsoft建议您在使用非托管资源时实施Dispose和Finalize。那么正确的顺序就是   是供开发人员调用Dispose。 Finalize实施会   运行,当对象出现时,资源仍将被释放   即使开发人员忽略了调用Dispose,也会收集垃圾   方法明确。 Francesco Balena在他的博客中写道:   只有在类型调用时才应使用Dispose / Finalize模式   分配非托管资源的非托管代码(包括非托管资源)   内存)并返回一个必须最终用于释放的句柄   资源。处置和最终确定必须链接到他们的父母   对象通过调用父对象的方法后调用它们   处理或完成自己的成员“。         简单地说,清理Finalize方法中的非托管资源和Dispose方法中的托管资源,   Dispose / Finalize模式已在您的代码中使用。

现在我又困惑了。在整篇文章和代码示例中,显示应在Dispose()中释放非托管资源。但那个评论的相关性是什么?

修改

确认这一行:

  

简单地说,清理Finalize方法中的非托管资源   Dispose方法中的托管方法,当Dispose / Finalize时   模式已在您的代码中使用

是错误的,我编辑了this answer

2 个答案:

答案 0 :(得分:36)

看得很简单。

  1. 如果您正在处理非托管资源 - 同时实施 Dispose Finalize 。开发人员会调用Dispose,以便在资源不再需要时立即释放资源。如果他们忘记调用Dispose,那么Framework会在自己的GC循环中调用finalize(通常会花费自己的甜蜜时间)。
  2. 如果您不处理非托管资源 - 那么就不要做任何事情。不要实施FinalizeDispose
  3. 如果您的对象在内部使用Disposable对象 - 如果您创建并保留了对实现Dispose()并且您没有'的类型的任何对象的引用,则实现Dispose()已经处理好了。
  4. 一些经典的例子:

    System.IO.FileStream 对象管理文件的锁/流句柄。所以它实现了dispose和finalize。如果开发人员处理它,那么另一个程序可以立即访问它。如果他忘记处理它,那么Framework会最终确定它并在GC循环中关闭句柄。

    System.Text.StringBuilder 没有任何非托管资源。所以没有处理完毕。

    就模式而言,

    意味着什么
    // Code to dispose the managed resources of the class
    

    调用您拥有的任何.NET对象的Dispose方法作为该类中的组件

    并且

    // Code to dispose the un-managed resources of the class
    

    意味着关闭原始句柄和指针。这是您的更新代码以及示例

    class Test : IDisposable
       {
         private bool isDisposed = false;
    
         ~Test()
         {
           Dispose(false);
         }
    
         protected void Dispose(bool disposing)
         {
           if (disposing)
           {
             // Code to dispose the managed resources of the class
             internalComponent1.Dispose();
             internalComponent2.Dispose();
           }
    
           // Code to dispose the un-managed resources of the class
           CloseHandle(handle);
           handle = IntPtr.Zero;   
    
           isDisposed = true;
         }
    
         public void Dispose()
         {
           Dispose(true);
           GC.SuppressFinalize(this);
         }
       }
    

    Here is an old question解释

答案 1 :(得分:3)

如果Foo的资源可以从确定性清理中受益,但没有一个可以在终结器中清除,则应该实现IDisposable但不应覆盖Finalize或者析构函数。如果一个类拥有多个资源,并且至少有一个资源可以在终结器中清理,那么可以在终结器中清理的每个离散资源都应该封装到自己的Finalizer /析构函数对象中(可以在protected嵌套类),包含这些资源的类应该包含对包装器对象的引用。完成后,外部类将适合具有Dispose方法但没有终结器/析构函数的类的模式。