本文引自:[Luminji]http://m.survivalescaperooms.com/luminji/archive/2011/03/29/1997812.html
需要明確一下C#程序(或者說.NET)中的資源。簡(jiǎn)單的說來,C#中的每一個(gè)類型都代表一種資源,而資源又分為兩類:
托管資源:由CLR管理分配和釋放的資源,即由CLR里new出來的對(duì)象;
非托管資源:不受CLR管理的對(duì)象,windows內(nèi)核對(duì)象,如文件、數(shù)據(jù)庫(kù)連接、套接字、COM對(duì)象等;
毫無例外地,如果我們的類型使用到了非托管資源,或者需要顯式釋放的托管資源,那么,就需要讓類型繼承接口IDisposable。這相當(dāng)于是告訴調(diào)用者,該類型是需要顯式釋放資源的,你需要調(diào)用我的Dispose方法。
不過,這一切并不這么簡(jiǎn)單,一個(gè)標(biāo)準(zhǔn)的繼承了IDisposable接口的類型應(yīng)該像下面這樣去實(shí)現(xiàn)。這種實(shí)現(xiàn)我們稱之為Dispose模式:
publicclass SampleClass : IDisposable { //演示創(chuàng)建一個(gè)非托管資源PRivate IntPtr nativeResource = Marshal.AllocHGlobal(100); //演示創(chuàng)建一個(gè)托管資源private AnotherResource managedResource =new AnotherResource(); privatebool disposed =false; ///<summary>/// 實(shí)現(xiàn)IDisposable中的Dispose方法 ///</summary>publicvoid Dispose() { //必須為true Dispose(true); //通知垃圾回收機(jī)制不再調(diào)用終結(jié)器(析構(gòu)器) GC.SuppressFinalize(this); } ///<summary>/// 不是必要的,提供一個(gè)Close方法僅僅是為了更符合其他語言(如C++)的規(guī)范 ///</summary>publicvoid Close() { Dispose(); } ///<summary>/// 必須,以備程序員忘記了顯式調(diào)用Dispose方法 ///</summary>~SampleClass() { //必須為false Dispose(false); } ///<summary>/// 非密封類修飾用protected virtual /// 密封類修飾用private ///</summary>///<param name="disposing"></param>protectedvirtualvoid Dispose(bool disposing) { if (disposed) { return; } if (disposing) { // 清理托管資源if (managedResource !=null) { managedResource.Dispose(); managedResource =null; } } // 清理非托管資源if (nativeResource != IntPtr.Zero) { Marshal.FreeHGlobal(nativeResource); nativeResource = IntPtr.Zero; } //讓類型知道自己已經(jīng)被釋放 disposed =true; } publicvoid SamplePublicMethod() { if (disposed) { thrownew ObjectDisposedException("SampleClass", "SampleClass is disposed"); } //省略 } }
在Dispose模式中,幾乎每一行都有特殊的含義。
在標(biāo)準(zhǔn)的Dispose模式中,我們注意到一個(gè)以~開頭的方法:
///<summary>/// 必須,以備程序員忘記了顯式調(diào)用Dispose方法 ///</summary>~SampleClass() { //必須為false Dispose(false); }
這個(gè)方法叫做類型的終結(jié)器。提供終結(jié)器的全部意義在于:我們不能奢望類型的調(diào)用者肯定會(huì)主動(dòng)調(diào)用Dispose方法,基于終結(jié)器會(huì)被垃圾回收器調(diào)用這個(gè)特點(diǎn),終結(jié)器被用做資源釋放的補(bǔ)救措施。
一個(gè)類型的Dispose方法應(yīng)該允許被多次調(diào)用而不拋異常。鑒于這個(gè)原因,類型內(nèi)部維護(hù)了一個(gè)私有的布爾型變量disposed:
private bool disposed = false;
在實(shí)際處理代碼清理的方法中,加入了如下的判斷語句:
if (disposed) { return; } //省略清理部分的代碼,并在方法的最后為disposed賦值為true disposed =true;這意味著類型如果被清理過一次,則清理工作將不再進(jìn)行。
應(yīng)該注意到:在標(biāo)準(zhǔn)的Dispose模式中,真正實(shí)現(xiàn)IDisposable接口的Dispose方法,并沒有實(shí)際的清理工作,它實(shí)際調(diào)用的是下面這個(gè)帶布爾參數(shù)的受保護(hù)的虛方法:
///<summary>/// 非密封類修飾用protected virtual /// 密封類修飾用private ///</summary>///<param name="disposing"></param> protectedvirtualvoid Dispose(bool disposing) { //省略代碼 }
之所以提供這樣一個(gè)受保護(hù)的虛方法,是為了考慮到這個(gè)類型會(huì)被其他類繼承的情況。如果類型存在一個(gè)子類,子類也許會(huì)實(shí)現(xiàn)自己的Dispose模式。受保護(hù)的虛方法用來提醒子類必須在實(shí)現(xiàn)自己的清理方法的時(shí)候注意到父類的清理工作,即子類需要在自己的釋放方法中調(diào)用base.Dispose方法。
還有,我們應(yīng)該已經(jīng)注意到了真正撰寫資源釋放代碼的那個(gè)虛方法是帶有一個(gè)布爾參數(shù)的。之所以提供這個(gè)參數(shù),是因?yàn)槲覀冊(cè)谫Y源釋放時(shí)要區(qū)別對(duì)待托管資源和非托管資源。
在供調(diào)用者調(diào)用的顯式釋放資源的無參Dispose方法中,調(diào)用參數(shù)是true:
publicvoid Dispose() { //必須為true Dispose(true); //其他省略 }Word-break: normal; word-spacing: 0px; margin: 10px auto; letter-spacing: normal; line-height: 16px; background-color: #ffffff; text-indent: 0px; -webkit-text-stroke-w
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注