当前位置:  开发笔记 > 编程语言 > 正文

为什么在析构函数中调用dispose(false)?

如何解决《为什么在析构函数中调用dispose(false)?》经验,为你挑选了3个好方法。

以下是典型的配置模式示例:

 public bool IsDisposed { get; private set; }

  #region IDisposable Members

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

  protected virtual void Dispose(bool disposing)
  {
    if (!IsDisposed)
    {
      if (disposing)
      {
        //perform cleanup here
      }

      IsDisposed = true;
    }
  }

  ~MyObject()
  {
    Dispose(false);
  }

我理解dispose的作用,但是我不明白你为什么要在析构函数中调用dispose(false)?如果你看一下这个定义它什么都不会做,那么为什么有人会编写这样的代码呢?根本不打算从析构函数中调用dispose 是不是有意义?



1> Guffa..:

如果由于某种原因未正确放置对象,则终结器用作后备.通常Dispose()会调用该方法,该方法将删除终结器连接并将对象转换为垃圾收集器可以轻松删除的常规托管对象.

以下是来自MSDN的一个示例,该类具有要清理的托管和非托管资源.

请注意,如果disposing为true,则仅清除托管资源,但始终清除非托管资源.

public class MyResource: IDisposable
{
    // Pointer to an external unmanaged resource.
    private IntPtr handle;
    // Other managed resource this class uses.
    private Component component = new Component();
    // Track whether Dispose has been called.
    private bool disposed = false;

    // The class constructor.
    public MyResource(IntPtr handle)
    {
        this.handle = handle;
    }

    // Implement IDisposable.
    // Do not make this method virtual.
    // A derived class should not be able to override this method.
    public void Dispose()
    {
        Dispose(true);
        // This object will be cleaned up by the Dispose method.
        // Therefore, you should call GC.SupressFinalize to
        // take this object off the finalization queue
        // and prevent finalization code for this object
        // from executing a second time.
        GC.SuppressFinalize(this);
    }

    // Dispose(bool disposing) executes in two distinct scenarios.
    // If disposing equals true, the method has been called directly
    // or indirectly by a user's code. Managed and unmanaged resources
    // can be disposed.
    // If disposing equals false, the method has been called by the
    // runtime from inside the finalizer and you should not reference
    // other objects. Only unmanaged resources can be disposed.
    private void Dispose(bool disposing)
    {
        // Check to see if Dispose has already been called.
        if(!this.disposed)
        {
            // If disposing equals true, dispose all managed
            // and unmanaged resources.
            if(disposing)
            {
                // Dispose managed resources.
                component.Dispose();
            }

            // Call the appropriate methods to clean up
            // unmanaged resources here.
            // If disposing is false,
            // only the following code is executed.
            CloseHandle(handle);
            handle = IntPtr.Zero;

            // Note disposing has been done.
            disposed = true;

        }
    }

    // Use interop to call the method necessary
    // to clean up the unmanaged resource.
    [System.Runtime.InteropServices.DllImport("Kernel32")]
    private extern static Boolean CloseHandle(IntPtr handle);

    // Use C# destructor syntax for finalization code.
    // This destructor will run only if the Dispose method
    // does not get called.
    // It gives your base class the opportunity to finalize.
    // Do not provide destructors in types derived from this class.
    ~MyResource()
    {
        // Do not re-create Dispose clean-up code here.
        // Calling Dispose(false) is optimal in terms of
        // readability and maintainability.
        Dispose(false);
    }
}


但请注意,如果你没有非托管资源,那么`Dispose(false)`完全没什么可做的 - 所以你根本不需要一个终结器,也不需要`Dispose(bool)`.我觉得标准模式过于复杂,无法满足几乎从未发生的用例(当他们这样做时,他们可能是一个坏主意).这是我更喜欢的一个:http://nitoprograms.blogspot.com/2009/08/how-to-implement-idisposable-and.html
@RomanStarkov的链接已移至http://blog.stephencleary.com/2009/08/how-to-implement-idisposable-and.html

2> stuartd..:

"这里的想法是,Dispose(布尔)知道它是否被调用进行显式清理(布尔值为true)而不是由于垃圾收集而被调用(布尔值为false).这种区别很有用,因为在处理时显式地,Dispose(Boolean)方法可以使用引用其他对象的引用类型字段安全地执行代码,知道这些其他对象尚未最终确定或处理.当布尔值为false时,Dispose(Boolean)方法应该不执行引用引用类型字段的代码,因为这些对象可能已经完成."

"处理,终结和资源管理设计指南"中有更多信息.

编辑:链接.



3> John Saunder..:

C#中没有析构函数.这是一个终结者,这是另一回事.

区别在于您是否需要清理托管对象.您不想尝试在终结器中清理它们,因为它们本身可能已经完成.


我刚刚碰巧看了C#编程指南的Destructors页面.它表明我在上面的回答中弄错了.特别是,析构函数和终结器之间存在差异:

class Car
{
    ~Car()  // destructor
    {
        // cleanup statements...
    }
}

相当于

protected override void Finalize()
{
    try
    {
        // Cleanup statements...
    }
    finally
    {
        base.Finalize();
    }
}

推荐阅读
围脖上的博博_771
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有