IDisposable 接口

定义

提供一种用于释放非托管资源的机制。Provides a mechanism for releasing unmanaged resources.

public interface class IDisposable
[System.Runtime.InteropServices.ComVisible(true)]
public interface IDisposable
type IDisposable = interface
Public Interface IDisposable
派生
属性

示例

下面的示例演示如何创建实现IDisposable接口的资源类。The following example demonstrates how to create a resource class that implements the IDisposable interface.

#using <System.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::ComponentModel;
using namespace System::Windows::Forms;

// The following example demonstrates how to create a class that 
// implements the IDisposable interface and the IDisposable.Dispose
// method with finalization to clean up unmanaged resources. 
//
public ref class MyResource: public IDisposable
{
private:

   // Pointer to an external unmanaged resource.
   IntPtr handle;

   // A managed resource this class uses.
   Component^ component;

   // Track whether Dispose has been called.
   bool disposed;

public:
   // The class constructor.
   MyResource( IntPtr handle, Component^ component )
   {
      this->handle = handle;
      this->component = component;
      disposed = false;
   }

   // This method is called if the user explicitly disposes of the
   // object (by calling the Dispose method in other managed languages, 
   // or the destructor in C++). The compiler emits as a call to 
   // GC::SuppressFinalize( this ) for you, so there is no need to 
   // call it here.
   ~MyResource() 
   {
      // Dispose of managed resources.
      component->~Component();

      // Call C++ finalizer to clean up unmanaged resources.
      this->!MyResource();

      // Mark the class as disposed. This flag allows you to throw an
      // exception if a disposed object is accessed.
      disposed = true;
   }

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

   // The C++ finalizer destructor ensures that unmanaged resources get
   // released if the user releases the object without explicitly 
   // disposing of it.
   //
   !MyResource()
   {      
      // Call the appropriate methods to clean up unmanaged 
      // resources here. If disposing is false when Dispose(bool,
      // disposing) is called, only the following code is executed.
      CloseHandle( handle );
      handle = IntPtr::Zero;
   }

};

void main()
{
   // Insert code here to create and use the MyResource object.
   MyResource^ mr = gcnew MyResource((IntPtr) 42, (Component^) gcnew Button());
   mr->~MyResource();
}
using System;
using System.ComponentModel;

// The following example demonstrates how to create
// a resource class that implements the IDisposable interface
// and the IDisposable.Dispose method.

public class DisposeExample
{
    // A base class that implements IDisposable.
    // By implementing IDisposable, you are announcing that
    // instances of this type allocate scarce resources.
    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.
        protected virtual 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);
        }
    }
    public static void Main()
    {
        // Insert code here to create
        // and use the MyResource object.
    }
}
Imports System.ComponentModel

' The following example demonstrates how to create
' a resource class that implements the IDisposable interface
' and the IDisposable.Dispose method.
Public Class DisposeExample

   ' A class that implements IDisposable.
   ' By implementing IDisposable, you are announcing that 
   ' instances of this type allocate scarce resources.
   Public Class MyResource
      Implements IDisposable
      ' Pointer to an external unmanaged resource.
      Private handle As IntPtr
      ' Other managed resource this class uses.
      Private component As component
      ' Track whether Dispose has been called.
      Private disposed As Boolean = False

      ' The class constructor.
      Public Sub New(ByVal handle As IntPtr)
         Me.handle = handle
      End Sub

      ' Implement IDisposable.
      ' Do not make this method virtual.
      ' A derived class should not be able to override this method.
      Public Overloads Sub Dispose() Implements IDisposable.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(Me)
      End Sub

      ' 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.
      Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
         ' Check to see if Dispose has already been called.
         If Not Me.disposed Then
            ' If disposing equals true, dispose all managed 
            ' and unmanaged resources.
            If disposing Then
               ' Dispose managed resources.
               component.Dispose()
            End If

            ' 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

         End If
      End Sub

      ' Use interop to call the method necessary  
      ' to clean up the unmanaged resource.
      <System.Runtime.InteropServices.DllImport("Kernel32")> _
      Private Shared Function CloseHandle(ByVal handle As IntPtr) As [Boolean]
      End Function

      ' This finalizer will run only if the Dispose method 
      ' does not get called.
      ' It gives your base class the opportunity to finalize.
      ' Do not provide finalize methods in types derived from this class.
      Protected Overrides Sub Finalize()
         ' Do not re-create Dispose clean-up code here.
         ' Calling Dispose(false) is optimal in terms of
         ' readability and maintainability.
         Dispose(False)
         MyBase.Finalize()
      End Sub
   End Class

   Public Shared Sub Main()
      ' Insert code here to create
      ' and use the MyResource object.
   End Sub

End Class

注解

此接口的主要用途是释放非托管资源。The primary use of this interface is to release unmanaged resources. 当不再使用对象时, 垃圾回收器会自动释放分配给托管对象的内存。The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. 但是, 无法预测何时会进行垃圾回收。However, it is not possible to predict when garbage collection will occur. 而且, 垃圾回收器不知道非托管资源, 如窗口句柄, 或者打开文件和流。Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams.

使用此Dispose接口的方法可与垃圾回收器一起显式释放非托管资源。Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector. 当不再需要对象时, 对象的使用者可以调用此方法。The consumer of an object can call this method when the object is no longer needed.

警告

这是将IDisposable接口添加到现有类的一项重大更改。It is a breaking change to add the IDisposable interface to an existing class. 由于您的类型的预先存在的使用者Dispose无法调用, 因此您不能确定您的类型持有的非托管资源是否会被释放。Because pre-existing consumers of your type cannot call Dispose, you cannot be certain that unmanaged resources held by your type will be released.

由于实现在不再需要某个实例所拥有的资源时由该类型的使用者调用, 因此应将托管对象包装SafeHandle在中 (建议的替代方法), 或应重写IDisposable.Dispose Object.Finalize当使用者忘记调用Dispose时, 释放非托管资源。Because the IDisposable.Dispose implementation is called by the consumer of a type when the resources owned by an instance are no longer needed, you should either wrap the managed object in a SafeHandle (the recommended alternative), or you should override Object.Finalize to free unmanaged resources in the event that the consumer forgets to call Dispose.

重要

在 .NET Framework 中, C++编译器支持对资源进行确定性处置, 并且不允许直接实现Dispose方法。In the .NET Framework, the C++ compiler supports deterministic disposal of resources and does not allow direct implementation of the Dispose method.

有关如何使用此接口和Object.Finalize方法的详细讨论, 请参阅垃圾回收实现 Dispose 方法主题。For a detailed discussion about how this interface and the Object.Finalize method are used, see the Garbage Collection and Implementing a Dispose Method topics.

使用实现 IDisposable 的对象Using an object that implements IDisposable

如果你的应用程序只使用一个实现IDisposable接口的对象, 则在使用完对象后, 应调用该对象的IDisposable.Dispose实现。If your app simply uses an object that implements the IDisposable interface, you should call the object's IDisposable.Dispose implementation when you are finished using it. 根据你的编程语言, 你可以通过以下两种方式之一执行此操作:Depending on your programming language, you can do this in one of two ways:

  • 通过使用语言构造 (如和中using C#的语句) Visual Basic。By using a language construct such as the using statement in C# and Visual Basic.

  • 通过IDisposable.Dispose try 在块中包装对/实现的调用。finallyBy wrapping the call to the IDisposable.Dispose implementation in a try/finally block.

备注

用于实现IDisposable的类型的文档说明事实, 并包括调用其Dispose实现的提醒。Documentation for types that implement IDisposable note that fact and include a reminder to call its Dispose implementation.

C#和 Visual Basic Using 语句The C# and Visual Basic Using statement

如果你的语言支持构造 (例如中 C#的 using 语句) 和using语句 Visual Basic 中, 则可以使用它, 而不是IDisposable.Dispose显式调用自己。If your language supports a construct such as the using statement in C# and the Using statement in Visual Basic, you can use it instead of explicitly calling IDisposable.Dispose yourself. 下面的示例使用此方法来定义WordCount保留文件的信息的类和其中的单词数。The following example uses this approach in defining a WordCount class that preserves information about a file and the number of words in it.

using System;
using System.IO;
using System.Text.RegularExpressions;

public class WordCount
{
   private String filename = String.Empty;
   private int nWords = 0;
   private String pattern = @"\b\w+\b"; 

   public WordCount(string filename)
   {
      if (! File.Exists(filename))
         throw new FileNotFoundException("The file does not exist.");
      
      this.filename = filename;
      string txt = String.Empty;
      using (StreamReader sr = new StreamReader(filename)) {
         txt = sr.ReadToEnd();
      }
      nWords = Regex.Matches(txt, pattern).Count;
   }
   
   public string FullName
   { get { return filename; } }
   
   public string Name
   { get { return Path.GetFileName(filename); } }
   
   public int Count 
   { get { return nWords; } }
}   
Imports System.IO
Imports System.Text.RegularExpressions

Public Class WordCount
   Private filename As String
   Private nWords As Integer
   Private pattern As String = "\b\w+\b" 

   Public Sub New(filename As String)
      If Not File.Exists(filename) Then
         Throw New FileNotFoundException("The file does not exist.")
      End If   
      
      Me.filename = filename
      Dim txt As String = String.Empty
      Using sr As New StreamReader(filename)
         txt = sr.ReadToEnd()
      End Using
      nWords = Regex.Matches(txt, pattern).Count
   End Sub
   
   Public ReadOnly Property FullName As String
      Get
         Return filename
      End Get   
   End Property
   
   Public ReadOnly Property Name As String
      Get
         Return Path.GetFileName(filename)
      End Get   
   End Property
   
   Public ReadOnly Property Count As Integer
      Get
         Return nWords
      End Get
   End Property
End Class

using语句实际上是语法上的便利。The using statement is actually a syntactic convenience. 在编译时, 语言编译器将为try / finally块实现中间语言 (IL)。At compile time, the language compiler implements the intermediate language (IL) for a try/finally block.

有关using语句的详细信息, 请参阅using 语句using 语句主题。For more information about the using statement, see the Using Statement or using Statement topics.

Try/Finally 块The Try/Finally block

如果编程语言不支持像或using Visual Basic 中C#的语句这样的构造, 或者不想使用它, IDisposable.Dispose则可以从finally try /语句。 finallyIf your programming language does not support a construct like the using statement in C# or Visual Basic, or if you prefer not to use it, you can call the IDisposable.Dispose implementation from the finally block of a try/finally statement. 下面的示例将上using一示例try / finally中的块替换为块。The following example replaces the using block in the previous example with a try/finally block.

using System;
using System.IO;
using System.Text.RegularExpressions;

public class WordCount
{
   private String filename = String.Empty;
   private int nWords = 0;
   private String pattern = @"\b\w+\b"; 

   public WordCount(string filename)
   {
      if (! File.Exists(filename))
         throw new FileNotFoundException("The file does not exist.");
      
      this.filename = filename;
      string txt = String.Empty;
      StreamReader sr = null;
      try {
         sr = new StreamReader(filename);
         txt = sr.ReadToEnd();
      }
      finally {
         if (sr != null) sr.Dispose();     
      }
      nWords = Regex.Matches(txt, pattern).Count;
   }
   
   public string FullName
   { get { return filename; } }
   
   public string Name
   { get { return Path.GetFileName(filename); } }
   
   public int Count 
   { get { return nWords; } }
}   
Imports System.IO
Imports System.Text.RegularExpressions

Public Class WordCount
   Private filename As String
   Private nWords As Integer
   Private pattern As String = "\b\w+\b" 

   Public Sub New(filename As String)
      If Not File.Exists(filename) Then
         Throw New FileNotFoundException("The file does not exist.")
      End If   
      
      Me.filename = filename
      Dim txt As String = String.Empty
      Dim sr As StreamReader = Nothing
      Try
         sr = New StreamReader(filename)
         txt = sr.ReadToEnd()
      Finally
         If sr IsNot Nothing Then sr.Dispose() 
      End Try
      nWords = Regex.Matches(txt, pattern).Count
   End Sub
   
   Public ReadOnly Property FullName As String
      Get
         Return filename
      End Get   
   End Property
   
   Public ReadOnly Property Name As String
      Get
         Return Path.GetFileName(filename)
      End Get   
   End Property
   
   Public ReadOnly Property Count As Integer
      Get
         Return nWords
      End Get
   End Property
End Class

有关finally模式的详细信息try / , 请参阅Try .。。Catch .。。Finally 语句, try finallytry-catch finally 语句For more information about the try/finally pattern, see Try...Catch...Finally Statement, try-finally, or try-finally Statement.

正在实现 IDisposableImplementing IDisposable

仅当类型IDisposable直接使用非托管资源时, 才应实现。You should implement IDisposable only if your type uses unmanaged resources directly. 当不再需要该实例时, 类型IDisposable.Dispose使用者可以调用你的实现来释放资源。The consumers of your type can call your IDisposable.Dispose implementation to free resources when the instance is no longer needed. 若要处理其无法调用Dispose的情况, 您应该使用从SafeHandle派生的类来包装非托管资源, Object.Finalize或者您应该为引用类型重写方法。To handle cases in which they fail to call Dispose, you should either use a class derived from SafeHandle to wrap the unmanaged resources, or you should override the Object.Finalize method for a reference type. 在任一情况下, Dispose使用方法可以在使用非托管资源 (例如释放、释放或重置非托管资源) 后执行任何需要的清理。In either case, you use the Dispose method to perform whatever cleanup is necessary after using the unmanaged resources, such as freeing, releasing, or resetting the unmanaged resources.

重要

如果要定义一个使用非托管资源的基类, 并且该基类具有、或可能已释放的子类, 则应实现IDisposable.Dispose方法并提供的第二个Dispose重载, 如以下区.If you are defining a base class that uses unmanaged resources and that either has, or is likely to have, subclasses that should be disposed, you should implement the IDisposable.Dispose method and provide a second overload of Dispose, as discussed in the next section.

IDisposable 和继承层次结构IDisposable and the inheritance hierarchy

具有应可释放的子类的基类必须按如下IDisposable方式实现。A base class with subclasses that should be disposable must implement IDisposable as follows. 当你对任何不是IDisposable sealed (NotInheritable在 Visual Basic 中) 的类型实现时, 都应使用此模式。You should use this pattern whenever you implement IDisposable on any type that isn't sealed (NotInheritable in Visual Basic).

  • 它应提供一个公共、非虚拟Dispose()方法和受保护的虚拟Dispose(Boolean disposing)方法。It should provide one public, non-virtual Dispose() method and a protected virtual Dispose(Boolean disposing) method.

  • 方法必须调用Dispose(true) , 并且应禁止终止以提高性能。 Dispose()The Dispose() method must call Dispose(true) and should suppress finalization for performance.

  • 基类型不应包括任何终结器。The base type should not include any finalizers.

下面的代码段反映了基类的释放模式。The following code fragment reflects the dispose pattern for base classes. 它假定您的类型不重写Object.Finalize方法。It assumes that your type does not override the Object.Finalize method.

using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;

class BaseClass : IDisposable
{
   // Flag: Has Dispose already been called?
   bool disposed = false;
   // Instantiate a SafeHandle instance.
   SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
   
   // Public implementation of Dispose pattern callable by consumers.
   public void Dispose()
   { 
      Dispose(true);
      GC.SuppressFinalize(this);           
   }
   
   // Protected implementation of Dispose pattern.
   protected virtual void Dispose(bool disposing)
   {
      if (disposed)
         return; 
      
      if (disposing) {
         handle.Dispose();
         // Free any other managed objects here.
         //
      }
      
      disposed = true;
   }
}
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.InteropServices

Class BaseClass : Implements IDisposable
   ' Flag: Has Dispose already been called?
   Dim disposed As Boolean = False
   ' Instantiate a SafeHandle instance.
   Dim handle As SafeHandle = New SafeFileHandle(IntPtr.Zero, True)

   ' Public implementation of Dispose pattern callable by consumers.
   Public Sub Dispose() _
              Implements IDisposable.Dispose
      Dispose(True)
      GC.SuppressFinalize(Me)           
   End Sub
   
   ' Protected implementation of Dispose pattern.
   Protected Overridable Sub Dispose(disposing As Boolean)
      If disposed Then Return
      
      If disposing Then
         handle.Dispose()
         ' Free any other managed objects here.
         '
      End If
      
      disposed = True
   End Sub
End Class

如果重写Object.Finalize方法, 则类应实现以下模式。If you do override the Object.Finalize method, your class should implement the following pattern.

using System;

class BaseClass : IDisposable
{
   // Flag: Has Dispose already been called?
   bool disposed = false;
   
   // Public implementation of Dispose pattern callable by consumers.
   public void Dispose()
   { 
      Dispose(true);
      GC.SuppressFinalize(this);           
   }
   
   // Protected implementation of Dispose pattern.
   protected virtual void Dispose(bool disposing)
   {
      if (disposed)
         return; 
      
      if (disposing) {
         // Free any other managed objects here.
         //
      }
      
      // Free any unmanaged objects here.
      //
      disposed = true;
   }

   ~BaseClass()
   {
      Dispose(false);
   }
}
Class BaseClass : Implements IDisposable
   ' Flag: Has Dispose already been called?
   Dim disposed As Boolean = False
   
   ' Public implementation of Dispose pattern callable by consumers.
   Public Sub Dispose() _
              Implements IDisposable.Dispose
      Dispose(True)
      GC.SuppressFinalize(Me)           
   End Sub
   
   ' Protected implementation of Dispose pattern.
   Protected Overridable Sub Dispose(disposing As Boolean)
      If disposed Then Return
      
      If disposing Then
         ' Free any other managed objects here.
         '
      End If
      
      ' Free any unmanaged objects here.
      '
      disposed = True
   End Sub

   Protected Overrides Sub Finalize()
      Dispose(False)      
   End Sub
End Class

子类应实现以下可释放模式:Subclasses should implement the disposable pattern as follows:

  • 它们必须重写 Dispose(Boolean) 并调用基类 Dispose(Boolean) 实现。They must override Dispose(Boolean) and call the base class Dispose(Boolean) implementation.

  • 如果需要他们可以提供终结器。They can provide a finalizer if needed. 终结器必须调用 Dispose(false)The finalizer must call Dispose(false).

请注意, 派生类本身并不实现IDisposable接口, 并且不包含无参数Dispose方法。Note that derived classes do not themselves implement the IDisposable interface and do not include a parameterless Dispose method. 它们仅重写基类Dispose(Boolean)方法。They only override the base class Dispose(Boolean) method.

下面的代码段反映派生类的释放模式。The following code fragment reflects the dispose pattern for derived classes. 它假定您的类型不重写Object.Finalize方法。It assumes that your type does not override the Object.Finalize method.

using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;

class DerivedClass : BaseClass
{
   // Flag: Has Dispose already been called?
   bool disposed = false;
   // Instantiate a SafeHandle instance.
   SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);

   // Protected implementation of Dispose pattern.
   protected override void Dispose(bool disposing)
   {
      if (disposed)
         return; 
      
      if (disposing) {
         handle.Dispose();
         // Free any other managed objects here.
         //
      }
      
      // Free any unmanaged objects here.
      //

      disposed = true;
      // Call base class implementation.
      base.Dispose(disposing);
   }
}
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.InteropServices

Class DerivedClass : Inherits BaseClass 
   ' Flag: Has Dispose already been called?
   Dim disposed As Boolean = False
   ' Instantiate a SafeHandle instance.
   Dim handle As SafeHandle = New SafeFileHandle(IntPtr.Zero, True)

   ' Protected implementation of Dispose pattern.
   Protected Overrides Sub Dispose(disposing As Boolean)
      If disposed Then Return
      
      If disposing Then
         handle.Dispose()
         ' Free any other managed objects here.
         '
      End If
      
      ' Free any unmanaged objects here.
      '
      disposed = True
      
      ' Call base class implementation.
      MyBase.Dispose(disposing)
   End Sub
End Class

方法

Dispose()

执行与释放或重置非托管资源关联的应用程序定义的任务。Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

适用于

另请参阅