程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#基礎知識 >> C#中Dispose、析構函數、close的區別

C#中Dispose、析構函數、close的區別

編輯:C#基礎知識

 

一、Close與Dispose這兩種方法的區別

調用完了對象的Close方法後,此對象有可能被重新進行使用;而Dispose方法來說,此對象所占有的資源需要被標記為無用了,也就是此對象要被銷毀,不能再被使用。例如常見.Net類庫中的SqlConnection這個類,當調用完Close方法後,可以通過Open重新打開一個數據庫連接,當徹底不用這個對象了就可以調用Dispose方法來標記此對象無用,等待GC回收。

 

二、三者的區別如圖

 

 

  析構函數 Dispose方法 Close方法 意義 銷毀對象 銷毀對象 關閉對象資源 調用方式 不能被顯示調用,在GC回收是被調用 需要顯示調用或者通過using語句 需要顯示調用 調用時機 不確定 確定,在顯示調用或者離開using程序塊 確定,在顯示調用時

 

三、析構函數 和 Dispose 的說明

  •  Dispose需要實現IDisposable接口。  
  • Dispose由開發人員代碼調用,而析構函數由GC自動調用。
  • Dispose方法應釋放所有托管和非托管資源。而析構函數只應釋放非托管資源。因為析構函數由GC來判斷調用,當GC判斷某個對象不再需要的時候,則調用其析構方法,這時候該對象中可能還包含有其他有用的托管資源。
  • Dispose方法結尾處加上代碼“GC.SuppressFinalize(this);”,即告訴GC不需要再調用該對象的析構方法,否則,GC仍會在判斷該對象不再有用後調用其析構方法,雖然程序不會出錯,但影響系統性能。
  • 析構函數 和 Dispose 釋放的資源應該相同,這樣即使類使用者在沒有調用 Dispose 的情況下,資源也會在 Finalize 中得到釋放。
  • Finalize 不應為 public。
  • 通過系統GC頻繁的調用析構方法來釋放資源會降低系統性能,所以推薦顯示調用Dispose方法。
  • 有 Dispose 方法存在時,應該調用它,因為 Finalize 釋放資源通常是很慢的。

 

四、Close函數的說明

 Close 這個方法在不同的類中有不同的含義,並沒有任何規定要求 Close 具有特殊的含義,也就是說 Close 並不一定要釋放資源,您也可以讓 Close 方法表示“關門”。  不過,由於 Close 有“關”的意思,通常也把 Close 拿來釋放資源,這也是允許的。比如文件操作中,用 Close 釋放對象似乎比 Dispose 含義更准確,於是在設計類時,可以將 Close 設為 public,將 Dispose 設為 protected,然後由 Close 調用 Dispose。 也就是說 Close 表示什麼意思,它會不會釋放資源,完全由類設計者決定。網上說“Close 調用 Dispose”這種方法是很片面的。在 SqlConnection 中 Close 只是表示關閉數據庫連接,並沒有釋放 SqlConnection 這個對象資源。   根據經驗,Close 和 Dispose 同時存在的情況下(均為 public),Close 並不表示釋放資源,因為通常情況下,類設計者不應該使用兩個 public 方法來釋放相同的資源。

五、析構函數和Dispose方法實例 

 public class BaseResource: IDisposable 
 ...{ 
   ~BaseResource() 
   ...{ 
   // 為了保持代碼的可讀性性和可維護性,千萬不要在這裡寫釋放非托管資源的代碼 
   // 必須以Dispose(false)方式調用,以false告訴Dispose(bool disposing)函數是從垃圾回收器在調用 析構函數 時調用的 
      Dispose(false); 
   } 
   // 無法被客戶直接調用 
   // 如果 disposing 是 true, 那麼這個方法是被客戶直接調用的,那麼托管的,和非托管的資源都可以釋放 
   // 如果 disposing 是 false, 那麼函數是從垃圾回收器在調用Finalize時調用的,此時不應當引用其他托管對象所以,只能釋放非托管資源 
   protected virtual void Dispose(bool disposing) 
   ...{ 
   // 那麼這個方法是被客戶直接調用的,那麼托管的,和非托管的資源都可以釋放 
      if(disposing) 
      ...{ 
   // 釋放 托管資源 
         OtherManagedObject.Dispose(); 
      } 
   //釋放非托管資源 
      DoUnManagedObjectDispose(); 
   // 那麼這個方法是被客戶直接調用的,告訴垃圾回收器從Finalization隊列中清除自己,從而阻止垃圾回收器調用 析構函數 方法. 
      if(disposing) 
          GC.SuppressFinalize(this); 
   } 
   //可以被客戶直接調用 
   public void Dispose() 
   ...{ 
      //必須以Dispose(true)方式調用,以true告訴Dispose(bool disposing)函數是被客戶直接調用的 
      Dispose(true); 
   } 
 }
View Code


參考:

托管資源:由CLR管理分配和釋放的資源,即由CLR裡new出來的對象;

非托管資源:不受CLR管理的對象,windows內核對象,如文件、數據庫連接、套接字、COM對象等;

改善C#程序的建議4:C#中標准Dispose模式的實現

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved