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

以下是典型的configuration模式示例:

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

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

如果由于某种原因,对象没有正确处理,终结器将被用作回退。 通常情况下, Dispose()方法将被调用,它将删除终结器的连接,并将对象转换为垃圾收集器可以轻松移除的常规托pipe对象。

下面是MSDN中的一个示例,该类具有托pipe和非托pipe资源进行清理。

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

 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(布尔)知道它是否被调用来进行显式清理(布尔值为true)而不是由于垃圾收集而被调用(布尔值为false)。这种区别是有用的,因为当被configuration显式地,Dispose(Boolean)方法可以使用引用其他对象的引用types字段来安全地执行代码,这些字段确实知道这些其他对象还没有被定型或处理,当布尔值为假时,Dispose(Boolean)方法应该不要执行引用引用types字段的代码,因为这些对象可能已经完成了。“

“处置,最终确定和资源pipe理devise指南”中有更多的信息。

编辑:链接。

C#中没有析构函数。 这是一个终结者,这是一个不同的事情。

区别在于是否需要清理pipe理对象。 你不想试图在终结者中清理它们,因为它们本身可能已经完成。


我刚刚碰巧看了C#编程指南的析构函数页面。 这表明我在上面的答案中弄错了。 特别是,析构函数和终结函数之间有区别:

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

相当于

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

我认为这个混乱是由于你的例子中你没有释放任何非托pipe资源。 当通过垃圾回收来调用处置时,这些也需要被释放,并且将在检查之外被释放以进行disposing 。 请参阅与释放非托pipe资源有关的MSDN示例。 另外那个将会/应该在检查之外发生的是对任何基类Dispose方法的调用。

从引用的文章:

  protected override void Dispose(bool disposing) { if (disposing) { // Release managed resources. } // Release unmanaged resources. // Set large fields to null. // Call Dispose on your base class. base.Dispose(disposing); } 

在if(disposing)中,应该调用处理/closures具有非托pipe资源(例如数据库连接)的托pipe对象。调用终结器时,这些对象不再可到达,因此对象本身可以最终确定,需要打电话给他们处理。 同样,定稿的顺序是不确定的,所以你可能正在调用处置已经处理的对象。