实现 Dispose 方法Implementing a Dispose method

通过实现 Dispose 方法来释放应用程序使用的非托管资源。You implement a Dispose method to release unmanaged resources used by your application. .NET 垃圾回收器不分配或释放非托管内存。The .NET garbage collector does not allocate or release unmanaged memory.

对象清理模式(称为清理模式)对对象生存期强制施加顺序。The pattern for disposing an object, referred to as a dispose pattern, imposes order on the lifetime of an object. 释放模式仅用于访问非托管资源的对象,如文件和管道句柄、注册表句柄、等待句柄或指向非托管内存块的指针。The dispose pattern is used only for objects that access unmanaged resources, such as file and pipe handles, registry handles, wait handles, or pointers to blocks of unmanaged memory. 这是因为垃圾回收器在回收不使用的托管对象时非常高效,但无法回收非托管对象。This is because the garbage collector is very efficient at reclaiming unused managed objects, but it is unable to reclaim unmanaged objects.

释放模式有两种变体:The dispose pattern has two variations:

若要帮助确保始终正确地清理资源,Dispose 方法应该可以多次调用而不引发异常。To help ensure that resources are always cleaned up appropriately, a Dispose method should be callable multiple times without throwing an exception.

GC.KeepAlive 方法提供的代码示例演示了强行垃圾回收如何在回收对象的成员仍在执行时引起终结器运行。The code example provided for the GC.KeepAlive method shows how aggressive garbage collection can cause a finalizer to run while a member of the reclaimed object is still executing. 在较长的 KeepAlive 方法末尾最好调用 Dispose 方法。It is a good idea to call the KeepAlive method at the end of a lengthy Dispose method.

Dispose() 和 Dispose(Boolean)Dispose() and Dispose(Boolean)

IDisposable 接口需要实现单个无参数的方法 DisposeThe IDisposable interface requires the implementation of a single parameterless method, Dispose. 但是,释放模式需要实现两种 Dispose 方法:However, the dispose pattern requires two Dispose methods to be implemented:

  • 一种没有参数的公共非虚拟的(Visual Basic 中的 NonInheritableIDisposable.Dispose 实现。A public non-virtual (NonInheritable in Visual Basic) IDisposable.Dispose implementation that has no parameters.

  • 受保护的虚拟(Visual Basic 中的OverridableDispose 方法,其签名为:A protected virtual (Overridable in Visual Basic) Dispose method whose signature is:

    protected virtual void Dispose(bool disposing)
    
    Protected Overridable Sub Dispose(disposing As Boolean)
    

Dispose() 重载The Dispose() overload

由于公共、非虚拟的(Visual Basic 中的 NonInheritable)、无参数 Dispose 方法由该类型的使用者调用,因此其用途是释放非托管资源和指示终结器(如果存在)不必运行。Because the public, non-virtual (NonInheritable in Visual Basic), parameterless Dispose method is called by a consumer of the type, its purpose is to free unmanaged resources and to indicate that the finalizer, if one is present, doesn't have to run. 因此,它具有标准实现:Because of this, it has a standard implementation:

public void Dispose()
{
   // Dispose of unmanaged resources.
   Dispose(true);
   // Suppress finalization.
   GC.SuppressFinalize(this);
}
Public Sub Dispose() _
           Implements IDisposable.Dispose
   ' Dispose of unmanaged resources.
   Dispose(True)
   ' Suppress finalization.
   GC.SuppressFinalize(Me)
End Sub

Dispose 方法执行所有对象清理,使垃圾回收器不再需要调用对象的 Object.Finalize 重写。The Dispose method performs all object cleanup, so the garbage collector no longer needs to call the objects' Object.Finalize override. 因此,调用 SuppressFinalize 方法会阻止垃圾回收器运行终结器。Therefore, the call to the SuppressFinalize method prevents the garbage collector from running the finalizer. 如果类型没有终结器,则对 GC.SuppressFinalize 的调用不起作用。If the type has no finalizer, the call to GC.SuppressFinalize has no effect. 请注意,释放非托管资源的实际工作是通过第二次重载 Dispose 方法执行的。Note that the actual work of releasing unmanaged resources is performed by the second overload of the Dispose method.

Dispose(Boolean) 重载The Dispose(Boolean) overload

在第二个重载中,disposing 参数是 Boolean,用于指明方法调用是来自 Dispose 方法(值为 true),还是来自终结器(值为 false)。In the second overload, the disposing parameter is a Boolean that indicates whether the method call comes from a Dispose method (its value is true) or from a finalizer (its value is false).

方法的主体包含两个代码块:The body of the method consists of two blocks of code:

  • 释放非托管资源的块。A block that frees unmanaged resources. 无论 disposing 参数的值如何,都会执行此块。This block executes regardless of the value of the disposing parameter.

  • 释放托管资源的条件块。A conditional block that frees managed resources. 如果 disposing 的值为 true,则执行此块。This block executes if the value of disposing is true. 它释放的托管资源可包括:The managed resources that it frees can include:

    实现 IDisposable 的托管对象。Managed objects that implement IDisposable. 可用于调用其 Dispose 实现的条件块。The conditional block can be used to call their Dispose implementation. 如果你已使用安全句柄来包装非托管资源,则应在此处调用 SafeHandle.Dispose(Boolean) 实现。If you have used a safe handle to wrap your unmanaged resource, you should call the SafeHandle.Dispose(Boolean) implementation here.

    占用大量内存或使用短缺资源的托管对象。Managed objects that consume large amounts of memory or consume scarce resources. Dispose 方法中显式释放这些对象的速度快于垃圾回收器不确定性回收它们的速度。Freeing these objects explicitly in the Dispose method releases them faster than if they were reclaimed non-deterministically by the garbage collector.

如果方法调用来自终结器(即当 disposing 为 false),则仅执行释放非托管资源的代码。If the method call comes from a finalizer (that is, if disposing is false), only the code that frees unmanaged resources executes. 由于未定义垃圾回收器在终止期间销毁托管对象的顺序,因此使用 Dispose 的值调用此 false 重载将阻止终结器尝试释放可能已被回收的托管资源。Because the order in which the garbage collector destroys managed objects during finalization is not defined, calling this Dispose overload with a value of false prevents the finalizer from trying to release managed resources that may have already been reclaimed.

实现基类的释放模式Implementing the dispose pattern for a base class

如果实现基类的释放模式,则必须提供以下内容:If you implement the dispose pattern for a base class, you must provide the following:

重要

你应针对实现 Dispose() 并且不是 sealed(Visual Basic 中的 NotInheritable)的所有基类实现此模式。You should implement this pattern for all base classes that implement Dispose() and are not sealed (NotInheritable in Visual Basic).

  • 调用 Dispose 方法的 Dispose(Boolean) 实现。A Dispose implementation that calls the Dispose(Boolean) method.

  • 执行释放资源的实际工作的 Dispose(Boolean) 方法。A Dispose(Boolean) method that performs the actual work of releasing resources.

  • 从包装非托管资源的 SafeHandle 派生的类(推荐),或对 Object.Finalize 方法的重写。Either a class derived from SafeHandle that wraps your unmanaged resource (recommended), or an override to the Object.Finalize method. SafeHandle 类提供了一个使你无需编写代码的终结器。The SafeHandle class provides a finalizer that frees you from having to code one.

以下是一个常规模式,用于实现使用安全句柄的基类的释放模式:Here's the general pattern for implementing the dispose pattern for a base class that uses a safe handle.

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

备注

上一个示例使用 SafeFileHandle 对象阐释模式;可以使用派生自 SafeHandle 的任何对象来替代。The previous example uses a SafeFileHandle object to illustrate the pattern; any object derived from SafeHandle could be used instead. 请注意,该示例不会正确实例化其 SafeFileHandle 对象。Note that the example does not properly instantiate its SafeFileHandle object.

以下是一个常规模式,用于实现重写 Object.Finalize 的基类的释放模式。Here's the general pattern for implementing the dispose pattern for a base class that overrides Object.Finalize.

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

备注

在 C# 中,通过定义析构函数重写 Object.FinalizeIn C#, you override Object.Finalize by defining a destructor.

实现派生类的释放模式Implementing the dispose pattern for a derived class

从实现 IDisposable 接口的类派生的类不应实现 IDisposable,因为 IDisposable.Dispose 的基类实现由其派生类继承。A class derived from a class that implements the IDisposable interface shouldn't implement IDisposable, because the base class implementation of IDisposable.Dispose is inherited by its derived classes. 相反,若要实现派生类的释放模式,你可提供以下内容:Instead, to implement the dispose pattern for a derived class, you provide the following:

  • protected Dispose(Boolean) 方法,用于替代基类方法并执行释放派生类的资源的实际工作。A protected Dispose(Boolean) method that overrides the base class method and performs the actual work of releasing the resources of the derived class. 此方法还应调用基类的 Dispose(Boolean) 方法并传递参数的释放状态。This method should also call the Dispose(Boolean) method of the base class and pass its disposing status for the argument.

  • 从包装非托管资源的 SafeHandle 派生的类(推荐),或对 Object.Finalize 方法的重写。Either a class derived from SafeHandle that wraps your unmanaged resource (recommended), or an override to the Object.Finalize method. SafeHandle 类提供了一个使你无需编写代码的终结器。The SafeHandle class provides a finalizer that frees you from having to code one. 如果你提供了终结器,则应调用 disposing 参数为 falseDispose(Boolean) 重载。If you do provide a finalizer, it should call the Dispose(Boolean) overload with a disposing argument of false.

以下是一个常规模式,用于实现使用安全句柄的派生类的释放模式:Here's the general pattern for implementing the dispose pattern for a derived class that uses a safe handle:

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

备注

上一个示例使用 SafeFileHandle 对象阐释模式;可以使用派生自 SafeHandle 的任何对象来替代。The previous example uses a SafeFileHandle object to illustrate the pattern; any object derived from SafeHandle could be used instead. 请注意,该示例不会正确实例化其 SafeFileHandle 对象。Note that the example does not properly instantiate its SafeFileHandle object.

以下是一个常规模式,用于实现重写 Object.Finalize 的派生类的释放模式:Here's the general pattern for implementing the dispose pattern for a derived class that overrides Object.Finalize:

using System;

class DerivedClass : BaseClass
{
   // Flag: Has Dispose already been called?
   bool disposed = false;
   
   // Protected implementation of Dispose pattern.
   protected override void Dispose(bool disposing)
   {
      if (disposed)
         return; 
      
      if (disposing) {
         // Free any other managed objects here.
         //
      }
      
      // Free any unmanaged objects here.
      //
      disposed = true;
      
      // Call the base class implementation.
      base.Dispose(disposing);
   }

   ~DerivedClass()
   {
      Dispose(false);
   }
}
Class DerivedClass : Inherits BaseClass
   ' Flag: Has Dispose already been called?
   Dim disposed As Boolean = False
   
   ' Protected implementation of Dispose pattern.
   Protected Overrides 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

      ' Call the base class implementation.
      MyBase.Dispose(disposing)
   End Sub
   
   Protected Overrides Sub Finalize()
      Dispose(False)
   End Sub 
End Class

备注

在 C# 中,通过定义析构函数重写 Object.FinalizeIn C#, you override Object.Finalize by defining a destructor.

使用安全句柄Using safe handles

编写对象终结器的代码是一项复杂的任务,如果处理不好可能会出现问题。Writing code for an object's finalizer is a complex task that can cause problems if not done correctly. 因此,建议你构造 System.Runtime.InteropServices.SafeHandle 对象,而非实现终结器。Therefore, we recommend that you construct System.Runtime.InteropServices.SafeHandle objects instead of implementing a finalizer.

System.Runtime.InteropServices.SafeHandle 类派生的类通过无中断地分配和释放句柄来简化对象生存期问题。Classes derived from the System.Runtime.InteropServices.SafeHandle class simplify object lifetime issues by assigning and releasing handles without interruption. 它们包含可以保证在卸载应用程序域时运行的重要终结器。They contain a critical finalizer that is guaranteed to run while an application domain is unloading. 有关使用安全句柄的优势的更多信息,请参见System.Runtime.InteropServices.SafeHandleFor more information about the advantages of using a safe handle, see System.Runtime.InteropServices.SafeHandle. Microsoft.Win32.SafeHandles 命名空间中的以下派生类提供安全句柄:The following derived classes in the Microsoft.Win32.SafeHandles namespace provide safe handles:

使用安全句柄实现基类的释放模式Using a safe handle to implement the dispose pattern for a base class

下面的示例阐释了基类 DisposableStreamResource 的释放模式,此模式使用安全句柄封装非托管资源。The following example illustrates the dispose pattern for a base class, DisposableStreamResource, that uses a safe handle to encapsulate unmanaged resources. 它定义 DisposableResource 类,该类使用 SafeFileHandle 包装表示打开的文件的 Stream 对象。It defines a DisposableResource class that uses a SafeFileHandle to wrap a Stream object that represents an open file. DisposableResource 方法还包含一个属性 Size,该属性返回文件流中的总字节数。The DisposableResource method also includes a single property, Size, that returns the total number of bytes in the file stream.

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

public class DisposableStreamResource : IDisposable
{
   // Define constants.
   protected const uint GENERIC_READ = 0x80000000;
   protected const uint FILE_SHARE_READ = 0x00000001;
   protected const uint OPEN_EXISTING = 3;
   protected const uint FILE_ATTRIBUTE_NORMAL = 0x80;
   protected IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
   private const int INVALID_FILE_SIZE = unchecked((int) 0xFFFFFFFF);
   
   // Define Windows APIs.
   [DllImport("kernel32.dll", EntryPoint = "CreateFileW", CharSet = CharSet.Unicode)]
   protected static extern IntPtr CreateFile (
                                  string lpFileName, uint dwDesiredAccess, 
                                  uint dwShareMode, IntPtr lpSecurityAttributes, 
                                  uint dwCreationDisposition, uint dwFlagsAndAttributes, 
                                  IntPtr hTemplateFile);
   
   [DllImport("kernel32.dll")]
   private static extern int GetFileSize(SafeFileHandle hFile, out int lpFileSizeHigh);
    
   // Define locals.
   private bool disposed = false;
   private SafeFileHandle safeHandle; 
   private long bufferSize;
   private int upperWord;
   
   public DisposableStreamResource(string filename)
   {
      if (filename == null)
         throw new ArgumentNullException("The filename cannot be null.");
      else if (filename == "")
         throw new ArgumentException("The filename cannot be an empty string.");
            
      IntPtr handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
                                 IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                                 IntPtr.Zero);
      if (handle != INVALID_HANDLE_VALUE)
         safeHandle = new SafeFileHandle(handle, true);
      else
         throw new FileNotFoundException(String.Format("Cannot open '{0}'", filename));
      
      // Get file size.
      bufferSize = GetFileSize(safeHandle, out upperWord); 
      if (bufferSize == INVALID_FILE_SIZE)
         bufferSize = -1;
      else if (upperWord > 0) 
         bufferSize = (((long)upperWord) << 32) + bufferSize;
   }
   
   public long Size 
   { get { return bufferSize; } }

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

   protected virtual void Dispose(bool disposing)
   {
      if (disposed) return;

      // Dispose of managed resources here.
      if (disposing)
         safeHandle.Dispose();
      
      // Dispose of any unmanaged resources not wrapped in safe handles.
      
      disposed = true;
   }  
}
Imports Microsoft.Win32.SafeHandles
Imports System.IO

Public Class DisposableStreamResource : Implements IDisposable
   ' Define constants.
   Protected Const GENERIC_READ As UInteger = &H80000000ui
   Protected Const FILE_SHARE_READ As UInteger = &H0000000i
   Protected Const OPEN_EXISTING As UInteger = 3
   Protected Const FILE_ATTRIBUTE_NORMAL As UInteger = &H80
   Protected INVALID_HANDLE_VALUE As New IntPtr(-1)
   Private Const INVALID_FILE_SIZE As Integer = &HFFFFFFFF
   
   ' Define Windows APIs.
   Protected Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (
                                         lpFileName As String, dwDesiredAccess As UInt32, 
                                         dwShareMode As UInt32, lpSecurityAttributes As IntPtr, 
                                         dwCreationDisposition As UInt32, dwFlagsAndAttributes As UInt32, 
                                         hTemplateFile As IntPtr) As IntPtr
   Private Declare Function GetFileSize Lib "kernel32" (hFile As SafeFileHandle, 
                                                        ByRef lpFileSizeHigh As Integer) As Integer
    
   ' Define locals.
   Private disposed As Boolean = False
   Private safeHandle As SafeFileHandle 
   Private bufferSize As Long 
   Private upperWord As Integer
   
   Public Sub New(filename As String)
      If filename Is Nothing Then
         Throw New ArgumentNullException("The filename cannot be null.")
      Else If filename = ""
         Throw New ArgumentException("The filename cannot be an empty string.")
      End If
            
      Dim handle As IntPtr = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
                                        IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                                        IntPtr.Zero)
      If handle <> INVALID_HANDLE_VALUE Then
         safeHandle = New SafeFileHandle(handle, True)
      Else
         Throw New FileNotFoundException(String.Format("Cannot open '{0}'", filename))
      End If
      
      ' Get file size.
      bufferSize = GetFileSize(safeHandle, upperWord) 
      If bufferSize = INVALID_FILE_SIZE Then
         bufferSize = -1
      Else If upperWord > 0 Then 
         bufferSize = (CLng(upperWord) << 32) + bufferSize
      End If     
   End Sub
   
   Public ReadOnly Property Size As Long
      Get
         Return bufferSize
      End Get
   End Property
   
   Public Sub Dispose() _
              Implements IDisposable.Dispose
      Dispose(True)
      GC.SuppressFinalize(Me)
   End Sub           

   Protected Overridable Sub Dispose(disposing As Boolean)
      If disposed Then Exit Sub

      ' Dispose of managed resources here.
      If disposing Then
         safeHandle.Dispose()
      End If
      
      ' Dispose of any unmanaged resources not wrapped in safe handles.
      
      disposed = True
   End Sub  
End Class

使用安全句柄实现派生类的释放模式Using a safe handle to implement the dispose pattern for a derived class

下面的示例阐释派生类 DisposableStreamResource2 的释放模式,该类继承自上一个示例中显示的 DisposableStreamResource 类。The following example illustrates the dispose pattern for a derived class, DisposableStreamResource2, that inherits from the DisposableStreamResource class presented in the previous example. 此类额外添加一种方法(即 WriteFileInfo),并使用 SafeFileHandle 对象包装可写文件的句柄。The class adds an additional method, WriteFileInfo, and uses a SafeFileHandle object to wrap the handle of the writable file.

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

public class DisposableStreamResource2 : DisposableStreamResource
{
   // Define additional constants.
   protected const uint GENERIC_WRITE = 0x40000000; 
   protected const uint OPEN_ALWAYS = 4;
   
   // Define additional APIs.
   [DllImport("kernel32.dll")]   
   protected static extern bool WriteFile(
                                SafeFileHandle safeHandle, string lpBuffer, 
                                int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten,
                                IntPtr lpOverlapped);
   
   // Define locals.
   private bool disposed = false;
   private string filename;
   private bool created = false;
   private SafeFileHandle safeHandle;
   
   public DisposableStreamResource2(string filename) : base(filename)
   {
      this.filename = filename;
   }
   
   public void WriteFileInfo()
   { 
      if (! created) {
         IntPtr hFile = CreateFile(@".\FileInfo.txt", GENERIC_WRITE, 0, 
                                   IntPtr.Zero, OPEN_ALWAYS, 
                                   FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
         if (hFile != INVALID_HANDLE_VALUE)
            safeHandle = new SafeFileHandle(hFile, true);
         else
            throw new IOException("Unable to create output file.");

         created = true;
      }

      string output = String.Format("{0}: {1:N0} bytes\n", filename, Size);
      int bytesWritten;
      bool result = WriteFile(safeHandle, output, output.Length, out bytesWritten, IntPtr.Zero);                                     
   }

   protected override void Dispose(bool disposing)
   {
      if (disposed) return;
      
      // Release any managed resources here.
      if (disposing)
         safeHandle.Dispose();
      
      disposed = true;
      
      // Release any unmanaged resources not wrapped by safe handles here.
      
      // Call the base class implementation.
      base.Dispose(disposing);
   }
}
Imports Microsoft.Win32.SafeHandles
Imports System.IO

Public Class DisposableStreamResource2 : Inherits DisposableStreamResource
   ' Define additional constants.
   Protected Const GENERIC_WRITE As Integer = &H40000000 
   Protected Const OPEN_ALWAYS As Integer = 4
   
   ' Define additional APIs.
   Protected Declare Function WriteFile Lib "kernel32.dll" (
                              safeHandle As SafeFileHandle, lpBuffer As String, 
                              nNumberOfBytesToWrite As Integer, ByRef lpNumberOfBytesWritten As Integer,
                              lpOverlapped As Object) As Boolean
   
   ' Define locals.
   Private disposed As Boolean = False
   Private filename As String
   Private created As Boolean = False
   Private safeHandle As SafeFileHandle
   
   Public Sub New(filename As String)
      MyBase.New(filename)
      Me.filename = filename
   End Sub
   
   Public Sub WriteFileInfo() 
      If Not created Then
         Dim hFile As IntPtr = CreateFile(".\FileInfo.txt", GENERIC_WRITE, 0, 
                                          IntPtr.Zero, OPEN_ALWAYS, 
                                          FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)
         If hFile <> INVALID_HANDLE_VALUE Then
            safeHandle = New SafeFileHandle(hFile, True)
         Else
            Throw New IOException("Unable to create output file.")
         End If
         created = True
      End If
      Dim output As String = String.Format("{0}: {1:N0} bytes {2}", filename, Size, 
                                           vbCrLf)
      WriteFile(safeHandle, output, output.Length, 0&, Nothing)                                     
   End Sub

   Protected Overloads Overridable Sub Dispose(disposing As Boolean)
      If disposed Then Exit Sub
      
      ' Release any managed resources here.
      If disposing Then
         safeHandle.Dispose()
      End If
      
      disposed = True
      ' Release any unmanaged resources not wrapped by safe handles here.
      
      ' Call the base class implementation.
      MyBase.Dispose(disposing)
   End Sub
End Class

请参阅See also