首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么要在析构函数中调用dispose(false)?

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

Stack Overflow用户
提问于 2009-03-10 02:49:05
回答 4查看 36.8K关注 0票数 66

下面是一个典型的dispose模式示例:

代码语言:javascript
复制
 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不是很有意义吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-03-10 03:11:24

终结器被用作后备,如果由于某种原因对象没有被正确地处理。通常,将调用Dispose()方法,该方法将移除终结器挂钩,并将对象转换为垃圾回收器可以轻松移除的常规托管对象。

下面是一个来自MSDN的示例,其中包含要清理的托管和非托管资源。

请注意,只有在disposing为true时,才会清理托管资源,但始终会清理非托管资源。

代码语言:javascript
复制
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);
    }
}
票数 51
EN

Stack Overflow用户

发布于 2009-03-10 02:53:25

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

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

我最近碰巧浏览了C#编程指南的Destructors页面。这表明我在上面的回答中是错误的。特别是,析构函数和终结器之间有一个区别:

代码语言:javascript
复制
class Car
{
    ~Car()  // destructor
    {
        // cleanup statements...
    }
}

等同于

代码语言:javascript
复制
protected override void Finalize()
{
    try
    {
        // Cleanup statements...
    }
    finally
    {
        base.Finalize();
    }
}
票数 9
EN

Stack Overflow用户

发布于 2009-03-10 02:59:48

在if(disposing)中,你应该在拥有非托管资源(例如数据库连接)的托管对象上调用dispose/close .When,终结器被称为终结器,这些对象不再可达,因此对象本身可以被终结,你不需要对它们调用dispose。另外,终结的顺序是不确定的,因此您可能会在已经释放的对象上调用dispose。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/628752

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档