本文為機器翻譯文章。如需檢視英文版,請選取 [原文] 核取方塊。您也可以將滑鼠指標移到文字上,即可在快顯視窗顯示英文原文。
譯文
原文

IDisposable 介面

 

提供用於釋放 Unmanaged 資源的機制。

若要瀏覽此類型的.NET Framework 原始程式碼,請參閱Reference Source

命名空間:   System
組件:  mscorlib (於 mscorlib.dll)

[ComVisibleAttribute(true)]
public interface IDisposable

名稱描述
System_CAPS_pubmethodDispose()

執行與釋放 (Free)、釋放 (Release) 或重設 Unmanaged 資源相關聯之應用程式定義的工作。

System_CAPS_note注意

若要檢視此類型的.NET Framework 原始程式碼,請參閱Reference Source 您可以瀏覽原始碼、 下載的參考,離線檢視,並逐步執行原始程式碼 (包含修補程式和更新),在偵錯;see instructions.

此介面的主要用途是釋放 unmanaged 的資源。 記憶體回收行程自動釋放該物件已不再使用時,配置給受管理物件的記憶體。 不過,不能夠預測何時會發生記憶體回收。 此外,記憶體回收行程不認得的視窗控制代碼等的 unmanaged 資源,或開啟檔案和資料流。

使用Dispose明確與記憶體回收行程釋放 unmanaged 的資源,搭配這個介面的方法。 物件的取用者不再需要物件時,可以呼叫這個方法。

System_CAPS_warning警告

它是中斷變更,以便加入IDisposable現有類別的介面。 因為您的型別既有的取用者無法呼叫Dispose,您就無法確定您的類型所持有的 unmanaged 的資源,將會釋放。

因為IDisposable.Dispose實作稱為取用者類型的執行個體所擁有的資源不再需要時,您可能必須換行中的受管理的物件SafeHandle(建議的替代做法),您應該覆寫或Object.Finalize釋放 unmanaged 的資源的消費者忘記呼叫Dispose

System_CAPS_important重要

在.NET Framework 中,c + + 編譯器支援決定性的資源處置,並不允許直接實作Dispose方法。

如需如何的詳細討論此介面和Object.Finalize方法可用,請參閱Garbage Collection實作 Dispose 方法主題。

實作IDisposable只有當您直接使用 unmanaged 的資源。 如果您的應用程式會直接使用該物件會實作IDisposable,沒有提供IDisposable實作。 相反地,您應該呼叫物件的IDisposable.Dispose實作,當您完成使用它。 根據您的程式語言,您可以執行下列其中一種︰

  • 使用的語言建構例如using在 C# 和 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 Statement (Visual Basic)using 陳述式 (C# 參考)主題。

如果您的程式語言不支援的建構,例如using陳述式,以 C# 或 Visual Basic 中,或如果您不想使用它,您可以呼叫IDisposable.Dispose實作從finally區塊try/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 Statement (Visual Basic)try-finally (C# 參考),或try-finally 陳述式 (C)

您應該實作IDisposable只有當您的類型會直接使用 unmanaged 的資源。 類型的消費者可以呼叫您IDisposable.Dispose實作,以執行個體已不再需要時釋放資源。 為了處理呼叫的失敗的情況Dispose,您應該的使用的類別衍生自SafeHandle包裝的 unmanaged 的資源,或您應覆寫Object.Finalize參考類型的方法。 在任一情況下,您可以使用Dispose方法,以執行任何清理之後需要使用的 unmanaged 的資源,例如,釋出、 釋放或重設 unmanaged 的資源。

System_CAPS_important重要

如果您要定義基底類別所使用的 unmanaged 的資源,,或可能有,應該處置的子類別,您應該實作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 起供應
回到頁首
顯示: