本文由机器翻译。若要查看英语原文,请勾选“英语”复选框。 也可将鼠标指针移到文本上,在弹出窗口中显示英语原文。
翻译
英语

IDisposable 接口

 

提供一种用于释放非托管资源的机制。

若要浏览此类型的.NET Framework 源代码,请参阅Reference Source

命名空间:   System
程序集:  mscorlib(位于 mscorlib.dll)

[ComVisibleAttribute(true)]
public interface IDisposable

名称说明
System_CAPS_pubmethodDispose()

执行与释放或重置非托管资源关联的应用程序定义的任务。

System_CAPS_note说明

若要查看此类型的.NET Framework 源代码,请参阅Reference Source 你可以浏览源代码联机,请下载离线查看的引用并在调试; 过程中逐步执行源 (包括修补程序和更新)see instructions.

此接口的主要用途是释放非托管的资源。 垃圾回收器自动释放不再使用该对象时分配给托管对象的内存。 但是,不可能预测将发生垃圾回收。 此外,垃圾回收器具有不知道如窗口句柄的非托管资源,或打开文件和流。

使用Dispose的此接口可显式释放垃圾回收器结合使用的非托管的资源的方法。 不再需要该对象时,对象的使用者可以调用此方法。

System_CAPS_warning警告

它是一项重大更改添加IDisposable到现有类的接口。 因为你类型的预先存在的使用者不能调用Dispose,则无法确保将释放由您的类型所持有的非托管的资源。

因为IDisposable.Dispose不再需要实例拥有的资源时,调用将实现由一种类型的使用者,应当换行中的托管的对象SafeHandle(建议的替代项),或应重写Object.Finalize释放非托管的资源中,使用者忘记调用Dispose

System_CAPS_important重要事项

在.NET Framework 中,c + + 编译器支持的资源进行确定性处置,并且不允许直接实现Dispose方法。

有关如何的详细讨论此接口与Object.Finalize方法使用,请参阅Garbage Collection实现 Dispose 方法主题。

实现IDisposable仅当直接使用非托管的资源。 如果你的应用程序只需使用实现的对象IDisposable,未提供IDisposable实现。 相反,应调用对象的IDisposable.Dispose实现在完成使用它时。 具体取决于您的编程语言,可以实现这两种方式之一︰

  • 通过使用一种语言构造 (如usingC# 和 Visual Basic 中的语句。

  • 通过包装到调用来IDisposable.Dispose中的实现try/catch块。

System_CAPS_note说明

文档类型实现IDisposable请注意这一事实,包括提醒调用其Dispose实现。

如果你的语言支持一种构造,如使用C# 中的语句和使用在 Visual Basic 中的语句,你可以使用它而不是显式调用IDisposable.Dispose自己。 下面的示例使用此方法中定义WordCount会保留有关文件和在其中的单词数的信息的类。

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

using语句是实际在语法上方便。 在编译时的语言编译器实现的中间语言 (IL) 以try/catch块。

有关详细信息using语句,请参阅Using 语句 (Visual Basic)using 语句(C# 参考)主题。

如果您的编程语言不支持类似的构造usingC# 或 Visual Basic 中的语句或如果你不希望使用它,则可以调用IDisposable.Dispose实现从finallytry/catch语句。 下面的示例替换using块中,与前面的示例在try/catch/finally块。

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

有关详细信息try/finally模式,请参阅Try...Catch...Finally 语句 (Visual Basic)try-finally(C# 参考),或try-finally 语句 (C)

应实现IDisposable仅当你的类型直接使用非托管的资源。 你的类型的使用者可以调用你IDisposable.Dispose实现实例不再需要时释放资源。 若要处理它们无法调用的情况Dispose,应从派生的类使用SafeHandle来包装非托管的资源,或你应该重写Object.Finalize对于引用类型的方法。 在任一情况下,你使用Dispose方法来执行任何清理后必须使用的非托管的资源,如释放或重置非托管的资源。

System_CAPS_important重要事项

如果你正在定义的基类,它使用非托管的资源和,具有,或可能有,应释放的子类,则应实现IDisposable.Dispose方法并提供的第二个重载Dispose下, 一节中所述。

具有应该是可释放的子类的基类必须实现IDisposable,如下所示。 每当你实现时,应使用此模式IDisposable上不是任何类型sealed(NotInheritable在 Visual Basic 中)。

  • 它应提供一个公共、非虚拟 Dispose() 方法和受保护的虚拟 Dispose(Boolean disposing) 方法。

  • Dispose()方法必须调用Dispose(true)和应该禁止显示性能的终止。

  • 基类型不应包括任何终结器。

下面的代码段反映基类的释放模式。 它假定你的类型不会覆盖Object.Finalize方法。

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.
         //
      }

      // Free any unmanaged objects here.
      //
      disposed = true;
   }
}

如果你重写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);
   }
}

子类应实现以下可释放模式:

  • 它们必须重写 Dispose(Boolean) 并调用基类 Dispose(Boolean) 实现。

  • 如果需要,他们可以提供终结器。 终结器必须调用 Dispose(false)

请注意,派生的类未本身实现IDisposable接口,但不包括无参数Dispose方法。 它们仅重写基类Dispose(Boolean)方法。

下面的代码段反映派生类的释放模式。 它假定你的类型不会覆盖Object.Finalize方法。

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

下面的示例演示如何实现资源类创建IDisposable接口。

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.
    }
}

通用 Windows 平台
自 8 起可用
.NET Framework
自 1.1 起可用
可移植类库
可移植 .NET 平台 中受支持
Silverlight
自 2.0 起可用
Windows Phone Silverlight
自 7.0 起可用
Windows Phone
自 8.1 起可用
返回页首
显示: