全面解讀C#編程中的析構(gòu)函數(shù)用法
析構(gòu)函數(shù)用于析構(gòu)類的實(shí)例。
備注
不能在結(jié)構(gòu)中定義析構(gòu)函數(shù)。只能對(duì)類使用析構(gòu)函數(shù)。
一個(gè)類只能有一個(gè)析構(gòu)函數(shù)。
無(wú)法繼承或重載析構(gòu)函數(shù)。
無(wú)法調(diào)用析構(gòu)函數(shù)。它們是被自動(dòng)調(diào)用的。
析構(gòu)函數(shù)既沒(méi)有修飾符,也沒(méi)有參數(shù)。
例如,下面是類 Car 的析構(gòu)函數(shù)的聲明:
class Car { ~Car() // destructor { // cleanup statements... } }
該析構(gòu)函數(shù)隱式地對(duì)對(duì)象的基類調(diào)用 Finalize。這樣,前面的析構(gòu)函數(shù)代碼被隱式地轉(zhuǎn)換為以下代碼:
protected override void Finalize() { try { // Cleanup statements... } finally { base.Finalize(); } }
這意味著對(duì)繼承鏈中的所有實(shí)例遞歸地調(diào)用 Finalize 方法(從派生程度最大的到派生程度最小的)。
注意
不應(yīng)使用空析構(gòu)函數(shù)。如果類包含析構(gòu)函數(shù),F(xiàn)inalize 隊(duì)列中則會(huì)創(chuàng)建一個(gè)項(xiàng)。調(diào)用析構(gòu)函數(shù)時(shí),將調(diào)用垃圾回收器來(lái)處理該隊(duì)列。如果析構(gòu)函數(shù)為空,只會(huì)導(dǎo)致不必要的性能損失。
程序員無(wú)法控制何時(shí)調(diào)用析構(gòu)函數(shù),因?yàn)檫@是由垃圾回收器決定的。垃圾回收器檢查是否存在應(yīng)用程序不再使用的對(duì)象。如果垃圾回收器認(rèn)為某個(gè)對(duì)象符合析構(gòu),則調(diào)用析構(gòu)函數(shù)(如果有)并回收用來(lái)存儲(chǔ)此對(duì)象的內(nèi)存。程序退出時(shí)也會(huì)調(diào)用析構(gòu)函數(shù)。
可以通過(guò)調(diào)用 Collect 強(qiáng)制進(jìn)行垃圾回收,但大多數(shù)情況下應(yīng)避免這樣做,因?yàn)檫@樣會(huì)導(dǎo)致性能問(wèn)題。
使用析構(gòu)函數(shù)釋放資源
通常,與運(yùn)行時(shí)不進(jìn)行垃圾回收的開發(fā)語(yǔ)言相比,C# 無(wú)需太多的內(nèi)存管理。這是因?yàn)?.NET Framework 垃圾回收器會(huì)隱式地管理對(duì)象的內(nèi)存分配和釋放。但是,當(dāng)應(yīng)用程序封裝窗口、文件和網(wǎng)絡(luò)連接這類非托管資源時(shí),應(yīng)當(dāng)使用析構(gòu)函數(shù)釋放這些資源。當(dāng)對(duì)象符合析構(gòu)時(shí),垃圾回收器將運(yùn)行對(duì)象的 Finalize 方法。
資源的顯式釋放
如果您的應(yīng)用程序在使用昂貴的外部資源,我們還建議您提供一種在垃圾回收器釋放對(duì)象前顯式地釋放資源的方式。可通過(guò)實(shí)現(xiàn)來(lái)自 IDisposable 接口的 Dispose 方法來(lái)完成這一點(diǎn),該方法為對(duì)象執(zhí)行必要的清理。這樣可大大提高應(yīng)用程序的性能。即使有這種對(duì)資源的顯式控制,析構(gòu)函數(shù)也是一種保護(hù)措施,可用來(lái)在對(duì) Dispose 方法的調(diào)用失敗時(shí)清理資源。
下面的示例創(chuàng)建三個(gè)類,這三個(gè)類構(gòu)成了一個(gè)繼承鏈。類 First 是基類,Second 是從 First 派生的,而 Third 是從 Second 派生的。這三個(gè)類都有析構(gòu)函數(shù)。在 Main() 中,創(chuàng)建了派生程度最大的類的實(shí)例。注意:程序運(yùn)行時(shí),這三個(gè)類的析構(gòu)函數(shù)將自動(dòng)被調(diào)用,并且是按照從派生程度最大的到派生程度最小的次序調(diào)用。
class First { ~First() { System.Diagnostics.Trace.WriteLine("First's destructor is called."); } } class Second : First { ~Second() { System.Diagnostics.Trace.WriteLine("Second's destructor is called."); } } class Third : Second { ~Third() { System.Diagnostics.Trace.WriteLine("Third's destructor is called."); } } class TestDestructors { static void Main() { Third t = new Third(); } }
輸出:
Third's destructor is called. Second's destructor is called. First's destructor is called.
析構(gòu)函數(shù)與Dispose()方法的區(qū)別
1. Dispose需要實(shí)現(xiàn)IDisposable接口。
2. Dispose由開發(fā)人員代碼調(diào)用,而析構(gòu)函數(shù)由GC自動(dòng)調(diào)用。
3. Dispose方法應(yīng)釋放所有托管和非托管資源。而析構(gòu)函數(shù)只應(yīng)釋放非托管資源。因?yàn)槲鰳?gòu)函數(shù)由GC來(lái)判斷調(diào)用,當(dāng)GC判斷某個(gè)對(duì)象不再需要的時(shí)候,則調(diào)用其析構(gòu)方法,這時(shí)候該對(duì)象中可能還包含有其他有用的托管資源。
4. 通過(guò)系統(tǒng)GC頻繁的調(diào)用析構(gòu)方法來(lái)釋放資源會(huì)降低系統(tǒng)性能,所以推薦顯示調(diào)用Dispose方法。
5. Dispose方法結(jié)尾處加上代碼“GC.SuppressFinalize(this);”,即告訴GC不需要再調(diào)用該對(duì)象的析構(gòu)方法,否則,GC仍會(huì)在判斷該對(duì)象不再有用后調(diào)用其析構(gòu)方法,雖然程序不會(huì)出錯(cuò),但影響系統(tǒng)性能。
6、析構(gòu)函數(shù) 和 Dispose 釋放的資源應(yīng)該相同,這樣即使類使用者在沒(méi)有調(diào)用 Dispose 的情況下,資源也會(huì)在 Finalize 中得到釋放。
7、Finalize 不應(yīng)為 public。
8、有 Dispose 方法存在時(shí),應(yīng)該調(diào)用它,因?yàn)?Finalize 釋放資源通常是很慢的。
相關(guān)文章
C#中DataTable排序、檢索、合并等操作實(shí)例
這篇文章主要介紹了C#中DataTable排序、檢索、合并等操作實(shí)例,其中詳細(xì)介紹了DataTable.Select的一些注意問(wèn)題和使用技巧等,需要的朋友可以參考下2014-04-04C# WINFORM 強(qiáng)制讓窗體獲得焦點(diǎn)的方法代碼
C# WINFORM 強(qiáng)制讓窗體獲得焦點(diǎn)的方法代碼,需要的朋友可以參考一下2013-04-04C#身份證識(shí)別相關(guān)技術(shù)功能詳解
這篇文章主要介紹了C#身份證識(shí)別相關(guān)技術(shù)詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07C# 實(shí)現(xiàn)階乘 (遞歸,非遞歸) 實(shí)現(xiàn)代碼
C# 實(shí)現(xiàn)階乘 (遞歸,非遞歸) 實(shí)現(xiàn)代碼,需要的朋友可以參考一下2013-05-05c# 使用特定帳號(hào)密碼訪問(wèn)Windows網(wǎng)路共享
這篇文章主要介紹了c# 使用特定帳號(hào)密碼訪問(wèn)Windows網(wǎng)路共享的方法,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03