C# Finalize和Dispose的區別

一:總結php

一、Finalize方法(C#中是析構函數,如下稱析構函數)是用於釋放非託管資源的,而託管資源會由GC自動回收。因此,咱們也能夠這樣來區分 託管和非託管資源。全部會由GC自動回收的資源,就是託管的資源,而不能由GC自動回收的資源,就是非託管資源。在咱們的類中直接使用非託管資源的狀況很 少,因此基本上不用咱們寫析構函數。

二、大部分的非託管資源會給系統帶來不少負面影響,例如數據庫鏈接不被釋放就可能致使鏈接池中的可用數據庫鏈接用盡。文件不關閉會致使其它進程沒法讀寫這個文件等等。

實現模型:
一、因爲大多數的非託管資源都要求能夠手動釋放,因此,咱們應該專門爲釋放非託管資源公開一個方法。實現IDispose接口的Dispose方法是最好的模型,由於C#支持using語句快,能夠在離開語句塊時自動調用Dispose方法。

二、雖然能夠手動釋放非託管資源,咱們仍然要在析構函數中釋放非託管資源,這樣纔是安全的應用程序。不然若是由於程序員的疏忽忘記了手動釋放非託管資源, 那麼就會帶來災難性的後果。因此說在析構函數中釋放非託管資源,是一種補救的措施,至少對於大多數類來講是如此。

三、因爲析構函數的調用將致使GC對對象回收的效率下降,因此若是已經完成了析構函數該乾的事情(例如釋放非託管資源),就應當使用SuppressFinalize方法告訴GC不須要再執行某個對象的析構函數。

四、析構函數中只能釋放非託管資源而不能對任何託管的對象/資源進行操做。由於你沒法預測析構函數的運行時機,因此,當析構函數被執行的時候,也許你進行操做的託管資源已經被釋放了。這樣將致使嚴重的後果。

五、(這是一個規則)若是一個類擁有一個實現了IDispose接口類型的成員,並建立(注意是建立,而不是接收,必須是由類本身建立)它的實例對象,則 這個類也應該實現IDispose接口,並在Dispose方法中調用全部實現了IDispose接口的成員的Dispose方法。
只有這樣的才能保證全部實現了IDispose接口的類的對象的Dispose方法可以被調用到,確保能夠手動釋聽任何須要釋放的資源。程序員

 

二:實現 Finalize 和 Dispose 以清理非託管資源

http://msdn.microsoft.com/zh-cn/library/b1yfkh5e(VS.80).aspx數據庫

 

http://www.sudu.cn/info/index.php?op=article&id=12170c#

三:維護內部非託管資源的託管類的手段:Finalize()--終結Dispose()--處置安全

非託管資源:原始的操做系統文件句柄,原始的非託管數據庫鏈接,非託管內存或其餘非託管資源。ide

Finalize()特性:函數

  • 重寫Finalize()的惟一緣由是,c#類經過PInvoke或複雜的COM互操做性任務使用了非託管資源(典型的狀況是經過System.Runtime.InteropServices.Marshal類型定義的各成員)注:PInvoke是平臺調用服務。
  • object中有finalize方法,但建立的類不能重寫此方法,若Overide會報錯,只能經過析構函數來達到一樣的效果。
  • Finalize方法的做用是保證.NET對象能在垃圾回收時清除非託管資源。
  • 在CLR在託管堆上分配對象時,運行庫自動肯定該對象是否提供一個自定義的Finalize方法。若是是這樣,對象會被標記爲可終結的,同時一個指向這個對象的指針被保存在名爲終結隊列的內部隊列中。終結隊列是一個由垃圾回收器維護的表,它指向每個在從堆上刪除以前必須被終結的對象。
  • 注意:Finalize雖然看似手動清除非託管資源,其實仍是由垃圾回收器維護,它的最大做用是確保非託管資源必定被釋放
  • 在結構上重寫Finalize是不合法的,由於結構是值類型,不在堆上,Finalize是垃圾回收器調用來清理託管堆的,而結構不在堆上。

Dispose()特性:編碼

  • 爲了更快更具操做性進行釋放,而非讓垃圾回收器(即不可預知)來進行,可使用Dispose,即實現IDispose接口.
  • 結構和類類型均可以實現IDispose(與重寫Finalize不一樣,Finalize只適用於類類型),由於不是垃圾回收器來調用Dispose方法,而是對象自己釋放非託管資源,如Car.Dispose().若是編碼時沒有調用Dispose方法,覺得着非託管資源永遠得不到釋放。
  • 若是對象支持IDisposable,老是要對任何直接建立的對象調用Dispose(),即有實現IDisposable接口的類對象都必須調用Dispose方法。應該認爲,若是類設計者選擇支持Dispose方法,這個類型就須要執行清除工做。記住一點,若是類型實現了IDisposable接口,調用Dispose方法老是正確的。
  • .net基類庫中許多類型都實現IDisposable接口,並使用了Dispose的別名,其中一個別名如IO中的Close方法,等等別名。使得看起來更天然。
  • using關鍵字,實際內部也是實現IDisposable方法,用ildasm.exe查看使用了using的代碼的CIL,會發現是用try/finally去包含using中的代碼,而且在finally中調用dispose方法。

我的總結:spa

相同點:操作系統

  • 都是爲了確保非託管資源獲得釋放。

不一樣點:

  • finalize由垃圾回收器調用;dispose由對象調用。
  • finalize無需擔憂由於沒有調用finalize而使非託管資源得不到釋放,而dispose必須手動調用。
  • finalize雖然無需擔憂由於沒有調用finalize而使非託管資源得不到釋放,但由於由垃圾回收器管理,不能保證當即釋放非託管資源;而dispose一調用便釋放非託管資源。
  • 只有類類型才能重寫finalize,而結構不能;類和結構都能實現IDispose.緣由請看Finalize()特性
相關文章
相關標籤/搜索