引言
在企業(yè)應(yīng)用開發(fā)世界,性能,靈活性和安全性是最重要的。我作為一個(gè)vc++程序員開始我的職業(yè)生涯,并且在一個(gè)晴朗的早晨,我被轉(zhuǎn)到了部。像每個(gè)c++程序員一樣,我也很失落。我想每個(gè)像tom,dick甚至harry能用html編程。然而,不久我就發(fā)現(xiàn)真正的挑戰(zhàn)是生產(chǎn)高性能的,靈活的可靠的應(yīng)用程序。綜上所述,web環(huán)境松耦合的,不分國界的本質(zhì)將使你永遠(yuǎn)神往。
為了制作高性能的靈活的應(yīng)用程序,用最優(yōu)化的方式使用你的資源是至關(guān)重要的。一個(gè)技巧是盡可能晚地使用你的資源并且在使用后盡快釋放它。我在這里的意圖是描述在c#中的對象清除機(jī)制。
解構(gòu)器
我們知道,‘解構(gòu)器’被用來清除類的事例。當(dāng)我們在c#中使用解構(gòu)器是,我們必須記住以下幾點(diǎn):
一個(gè)類只能有一個(gè)解構(gòu)器。
解構(gòu)器不能被繼承或重載。
解構(gòu)器不能被調(diào)用。他們是自動被(編譯器)調(diào)用的。
解構(gòu)器不能帶修飾或參數(shù)。
下面是類myclass解構(gòu)器的一個(gè)聲明:
~ myclass()
// cleaning up code goes here
}
程序員不能控制解構(gòu)器何時(shí)將被執(zhí)行因?yàn)檫@是由垃圾收集器決定的。垃圾收集器檢查不在被應(yīng)用程序使用的對象。它認(rèn)為這些條件是符合清楚的并且收回它們的內(nèi)存。解構(gòu)器也在程序退出時(shí)被調(diào)用。當(dāng)解構(gòu)器執(zhí)行時(shí)其背后所發(fā)生的那一幕是解構(gòu)器隱式調(diào)用對象基類的object.finalize方法。因此上述解構(gòu)器代碼被隱含轉(zhuǎn)化成:
protectedoverridevoid finalize()
{
try
{
// cleaning up .
}
finally
{
base.finalize();
}
}
現(xiàn)在,讓我們看一個(gè)解構(gòu)器怎樣被調(diào)用的例子。我們有三個(gè)類a,b和c。b派生自a,c派生自b。每個(gè)類有它們自己的構(gòu)造器和解構(gòu)。在類app的main函數(shù)中,我們創(chuàng)建c的對象。
using system;
class a{public a(){ console.writeline("creating a");}~a(){ console.writeline("destroying a"); }}class b:a{ public b() { console.writeline("creating b"); } ~b() { console.writeline("destroying b"); }} class c:b{ public c() { console.writeline("creating c"); } ~c() { console.writeline("destroying c"); }} class app{ publicstaticvoid main() { c c=new c(); console.writeline("object created "); console.writeline("press enter to destroy it"); console.readline(); c=null; //gc.collect(); console.read(); }} 正如我們預(yù)料的,基類的構(gòu)造器將會被執(zhí)行并且程序會等待用戶按‘enter’。當(dāng)這個(gè)發(fā)生,我們把類c的對象置為null.但解構(gòu)器沒有被執(zhí)行..!!??正像我們所說的,程序員無法控制解構(gòu)器何時(shí)被執(zhí)行因?yàn)檫@是由垃圾搜集器決定的。但程序退出時(shí)解構(gòu)器被調(diào)用了。你能通過重定向程序的o/p到文本文件來檢查這個(gè)。我將它輸出在這里。注意到基類的解構(gòu)器被調(diào)用了,因?yàn)樵诒澈骲ase.finalize()被調(diào)用了。
creating a
creating bcreating cobject created press enter to destroy itdestroying cdestroying bdestroying a 所以,如果一旦你使用完對象你就想調(diào)用解構(gòu)器,你該怎么做?有兩個(gè)方法:調(diào)用垃圾搜集器來清理。
實(shí)現(xiàn)idisposable的dispose方法。
調(diào)用垃圾搜集器
你能通過調(diào)用gc.collect方法強(qiáng)制垃圾搜集器來清理內(nèi)存,但在大多數(shù)情況下,這應(yīng)該避免因?yàn)樗鼤?dǎo)致性能問題。在上面的程序中,在gc.collect()處移除注釋。編譯并運(yùn)行它。現(xiàn)在,你能看到解構(gòu)器在控制臺中被執(zhí)行了。
實(shí)現(xiàn)idisposable接口
idisposable 接口包括僅有的一個(gè)公共方法,其聲明為void dispose()。我們能實(shí)現(xiàn)這個(gè)方法來關(guān)閉或釋放非托管資源如實(shí)現(xiàn)了這個(gè)接口的類事例所控制的文件,流,和句柄等。這個(gè)方法被用做所有任務(wù)聯(lián)合對象的資源釋放。當(dāng)實(shí)現(xiàn)了這個(gè)方法,對象必須尋求確保所有擁有的資源被繼承結(jié)構(gòu)中關(guān)聯(lián)的資源也釋放(不能把握,翻不出來)。
class myclass:idisposable
{publicvoid dispose() { //implementation }} 當(dāng)我們實(shí)現(xiàn)了idisposable接口時(shí),我們需要規(guī)則來確保dispose被適當(dāng)?shù)卣{(diào)用。
聯(lián)合使用解構(gòu)器和idisposable接口
public class myclass:idisposable
{private bool isdisposed=false;public void dispose(){ dispose(true); gc.supressfinalize(this);}protected void dispose(bool diposing){ if(!isdisposed) { if(disposing) { //clean up managed resources } //clean up unmanaged resources } isdisposed=true;} ~myclass(){ dispose(false);}} 在這里重載了dispose(bool)來做清理工作,并且所有的清理代碼都僅寫在這個(gè)方法中。這個(gè)方法被解構(gòu)器和idisposable.dispose()兩著調(diào)用。我們應(yīng)該注意dispose(bool)沒有在任何地方被調(diào)用除了在idisposable.dispose()和解構(gòu)器中。
當(dāng)一個(gè)客戶調(diào)用idisposable.dispose()時(shí),客戶特意地想要清理托管的和非托管資源,并且因此完成清理工作。有一件你必須注意的事情是我們在清理資源之后立即調(diào)用了gc.supressfinalize(this)。這個(gè)方法通知垃圾搜集器不需要調(diào)用解構(gòu)器,因?yàn)槲覀円呀?jīng)做了清理。
注意上面的例子,解構(gòu)器使用參數(shù)false調(diào)用dispose。這里,我們確信垃圾搜集器搜集了托管資源。我們僅僅做非托管資源的清理。
結(jié)論
盡管如此我們花費(fèi)一些時(shí)間實(shí)現(xiàn)idisposable接口,如果客戶不能合適地調(diào)用它們會怎樣?為此c#有一個(gè)酷的解決方案。‘using’代碼塊。它看起來像這樣:
using (myclass objcls =new myclass()){}
當(dāng)控制從using塊通過成功運(yùn)行到結(jié)束或者拋出異常退出時(shí),myclass的idispose.dispose()將會被執(zhí)行。記住你例示的對象必須實(shí)現(xiàn)system.idisposable接口。using語句定義了哪個(gè)對象將被清除的一個(gè)范圍。
新聞熱點(diǎn)
疑難解答
圖片精選