前面的文章我們說過,如果物件包含非託管資源那麼就必須要正確的清理,現在我們就來說一下如何清理。針對非託管資源 .net 會採用一套標準的模式來完成清理工作。也就是說如果開發人員自己編寫的類中存在非託管資源,那麼這個類的使用者就會認為這個類遵循 .net 的垃圾清理模式。標準的 dispose 模式即實現了 idisposable 介面,又實現了 finalizer ,這樣就可以在客戶端忘記呼叫 idisposable.dispose 的情況下也可以釋放資源。
tip:在 .net 中訪問非託管資源還可以通過system.runtime.interop.safehandle的派生類來訪問,該類正確實現了標準的 dispose 。零、基類與子類需要注意
在詳細講解具體如何正確實現 dispose 模式前我們要了解基類與子類需要注意的內容。
基類子類
一、詳解
當我們編寫的類中存在必須釋放的資源的時候,我們就必須實現 idisposable 介面,這個介面只包含乙個無返回值的無參 dispose 方法。在實現該方法時又如下幾個方面需要注意的:
釋放所有不再使用的非託管資源;
釋放所有不再使用的託管資源;
設定狀態標誌,表示物件已被清理過,如果有**呼叫被清理過的物件那麼就可以通過這個標誌得知,進而手動丟擲objectdisposedexception異常;
通過gc.supperssfinalize(this)來阻止垃圾**器重複清理已被清理過的物件。
雖然實現 dispose 方法在保證釋放託管資源和非託管資源的情況下又能保證程式效能不會下降,但是它依然存在問題。子類在清理自身資源的同時還必須保證基類資源也被清理掉。這時大部分開發人員能想到的解決方法就是重寫 finalizer並呼叫基類釋放資源的方法,或者給 dispos 方法新增新的邏輯並呼叫基類釋放資源的方法。這兩種方法都有類似的任務需要完成,因此這兩種方法包含了大量重複的**,這時我們就需要將這兩種方法中重複的**提取到乙個protected級別的虛函式種,這樣基類只需寫好核心邏輯,子類重寫這個方法用來釋放自己的資源就可以了。一般我們會將這個方法定義成如下的樣子:
protected
virtual
void
dispose
(bool isdisposing)
在上述**中如果 isdisposing 為 true,則代表託管資源和非託管資源都要清理,如果為 false 則代表只清理非託管資源。不管是 true 還是 false 我們都需要在子類中呼叫基類的 dispose(bool) 方法。下面我們通過一段**來看一下我們該怎麼實現上述所說的內容。
public
class
demobase
:idisposable
protected
virtual
void
dispose
(bool isdisposing)
if(isdisposing)
//清理非託管資源
basedisposed=
true;}
public
void
method()
//more code}}
public
class
demo
:demobase
if(isdisposing)
//清理非託管資源
base
.dispose
(isdisposing)
; disposed=
true;}
//more code
}
上述**中 demo 類繼承自 demobase,並重寫了 dispose 方法。我們在**中看到基類和子類都使用了標誌狀態(basedisposed,disposed),這裡為什麼不使用同乙個標誌狀態呢?主要是因為子類在釋放資源的時候有可能會把標誌狀態改為 true,這時在執行基類的 dispose(bool) 方法基類會認為資源已經釋放過了。
tip:dispose(bool) 和 finalizer 都必須編寫的很可靠,同時具備冪等性。也就是說無論多少次呼叫 dispose(bool) 的效果都是一樣的。並且我們在釋放資源的時候我們不應該進行除了釋放資源以外的操作。
C 中標準Dispose模式的實現
摘要 c 程式中的dispose方法,一旦被呼叫了該方法的物件,雖然還沒有垃圾 但實際上已經不能再使用了。所以使用上要仔細考慮細節。需要明確一下c 程式 或者說.net 中的資源。簡單的說來,c 中的每乙個型別都代表一種資源,而資源又分為兩類 託管資源 由clr管理分配和釋放的資源,即由clr裡ne...
關於Dispose 的問題
當我懷著美好的心情翻閱dot 文件的時候,dispose令人厭惡的進入了我的視線。首先,我意識到文件裡面所說的,某些物件必須手工呼叫dispose,並不是一句玩笑話。文件裡面提到的這個要求是嚴肅的認真的。比如sqlconnection,雖然你不手工呼叫dispose或者close在某些情況下也可以,...
C Finalize和Dispose的區別
一 總結 1 finalize方法 c 中是析構函式,以下稱析構函式 是用於釋放非託管資源的,而託管資源會由gc自動 所以,我們也可以這樣來區分 託管和非託管資源。所有會由gc自動 的資源,就是託管的資源,而不能由gc自動 的資源,就是非託管資源。在我們的類中直接使用非託管資源的情況很 少,所以基本...