.NET中IDisposable介面的基本使用

來源:互聯網
上載者:User

標籤:style   blog   http   io   ar   color   os   使用   sp   

首先來看MSDN中關於這個介面的說明:

[ComVisible(true)]public interface IDisposable{    // Methods    void Dispose();}
1.[ComVisible(true)]:指示該託管類型對 COM 是可見的.

2.此介面的主要用途是釋放非託管資源。當不再使用託管對象時,記憶體回收行程會自動釋放分配給該對象的記憶體。但無法預測進行記憶體回收的時間。另外,記憶體回收行程對視窗控制代碼或開啟的檔案和流等非託管資源一無所知。將此介面的Dispose方法與記憶體回收行程一起使用來顯式釋放非託管資源。當不再需要對象時,對象的使用者可以調用此方法。

一:基本應用

1.我們來定義一個實現了IDisposable介面的類,代碼如下:

 public class CaryClass :IDisposable
{ public void DoSomething() { Console.WriteLine("Do some thing...."); } public void Dispose() { Console.WriteLine("及時釋放資源"); } }
2.我們有兩種方式來調用:
2.1.第一種方式,使用Using語句會自動調用Dispose方法,代碼如下:
  using (CaryClass caryClass = new CaryClass())  {      caryClass.DoSomething();  }
2.2第二種方式,現實調用該介面的Dispose方法,代碼如下:
  CaryClass caryClass = new CaryClass();   try    {       caryClass.DoSomething();                   }   finally    {       IDisposable disposable = caryClass as IDisposable;       if (disposable != null) disposable.Dispose();    }
兩種方式的執行結果是一樣的,如:
 
2.3.使用try/finally 塊比使用 using 塊的好處是即使using中的代碼引發異常,CaryClass的Dispose方法仍有機
會清理該對象。所以從這裡看還是使用try/catch好一些。

二:Disposable 模式
1.在.NET種由於當對象變為不可訪問後將自動調用Finalize方法,所以我們手動調用IDisposable介面的Dispose方法
和對象終結器調用的方法極其類似,我們最好將他們放到一起來處理。我們首先想到的是重寫Finalize方法,如下:
protected override void Finalize(){     Console.WritleLine("解構函式執行...");}
當我們編譯這段代碼的時候,我們發現編譯器會報如下的錯誤:
 
這是因為編譯器徹底屏蔽了父類的Finalize方法,編譯器提示我們如果要重寫Finalize方法我們要提供一個解構函式來
代替,下面我們就提供一個解構函式:
  ~CaryClass()  {      Console.WriteLine("解構函式執行...");  }
實際上這個解構函式編譯器會將其轉變為如下代碼:
protected override void Finalize(){   try   {     Console.WritleLine("解構函式執行...");   }   finally   {     base.Finalize();   }}
2.然後我們就可以將Dispose方法的調用和對象的終結器放在一起來處理,如下:
public class CaryClass: IDisposable{    ~CaryClass()    {        Dispose();    }    public void Dispose()    {        // 清理資源
}
}
3.上面實現方式實際上調用了Dispose方法和Finalize方法,這樣就有可能導致做重複的清理工作,所以就有了下面經典
Disposable 模式:
 private bool IsDisposed=false;   public void Dispose()   {       Dispose(true);       GC.SupressFinalize(this);   }   protected void Dispose(bool Diposing)   {       if(!IsDisposed)       {           if(Disposing)           {              //清理託管資源
} //清理非託管資源 } IsDisposed=true; } ~CaryClass() { Dispose(false); }

3.1. SupressFinalize方法以防止記憶體回收行程對不需要終止的對象調用 Object.Finalize()。
3.2. 使用IDisposable.Dispose 方法,使用者可以在可將對象作為記憶體回收之前隨時釋放資源。如果調用了 IDisposable.Dispose 方法,此方法會釋放對象的資源。這樣,就沒有必要進行終止。IDisposable.Dispose 應調用 GC.SuppressFinalize 以使記憶體回收行程不調用對象的終結器。
3.3.我們不希望Dispose(bool Diposing)方法被外部調用,所以他的存取層級為protected 。如果Diposing為true則釋放託管資源和非託管資源,如果 Diposing等於false則該方法已由運行庫從終結器內部調用,並且只能釋放非託管資源。
3.4.如果在對象被釋放後調用其他方法,則可能會引發 ObjectDisposedException。

三:執行個體解析

1.下面代碼對Dispose方法做了封裝,說明如何在使用託管和本機資源的類中實現 Dispose(bool) 的常規樣本:
public class BaseResource : IDisposable    {        // 非託管資源        private IntPtr handle;        //託管資源        private Component Components;        // Dispose是否被調用        private bool disposed = false;        public BaseResource()        {                    }               public void Dispose()        {            Dispose(true);                        GC.SuppressFinalize(this);        }        protected virtual void Dispose(bool disposing)        {                       if (!this.disposed)                      {                               if (disposing)                {                    // 釋放託管資源                    Components.Dispose();                }                // 釋放非託管資源,如果disposing為false,                 // 只有託管資源被釋放                CloseHandle(handle);                handle = IntPtr.Zero;                // 注意這裡不是安全執行緒的            }            disposed = true;        }        // 解構函式只會在我們沒有直接調用Dispose方法的時候調用        // 衍生類別中不用在次提供解構函式        ~BaseResource()        {            Dispose(false);        }        // 如果你已經調用了Dispose方法後在調用其他方法會拋出ObjectDisposedException        public void DoSomething()        {            if (this.disposed)            {                throw new ObjectDisposedException();            }        }    }        public class MyResourceWrapper : BaseResource    {        // 託管資源        private ManagedResource addedManaged;        // 非託管資源        private NativeResource addedNative;        private bool disposed = false;               public MyResourceWrapper()        {                   }        protected override void Dispose(bool disposing)        {            if (!this.disposed)            {                try                {                    if (disposing)                    {                                                addedManaged.Dispose();                    }                                        CloseHandle(addedNative);                    this.disposed = true;                }                finally                {                                       base.Dispose(disposing);                }            }        }    }

2.使用CLR垃圾收集器,您不必再擔心如何管理對託管堆分配的記憶體,不過您仍需清理其他類型的資源。託管類通過
IDisposable 介面使其使用方可以在垃圾收集器終結對象前釋放可能很重要的資源。通過遵循 disposable 模式並且留
意需注意的問題,類可以確保其所有資源得以正確清理,並且在直接通過 Dispose 調用或通過終結器線程運行清理代碼時
不會發生任何問題。

.NET中IDisposable介面的基本使用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.