C#托管及未托管對(duì)象管理
c#中的對(duì)象分為值類型和引用類型,二者最大的區(qū)別在于數(shù)據(jù)的存儲(chǔ)方式和存儲(chǔ)位置.WINDOWS操作系統(tǒng)使用虛擬尋址系統(tǒng)來管理程序運(yùn)行時(shí)產(chǎn)生的數(shù)據(jù)存放.簡(jiǎn)單的說,該系統(tǒng)管理著一個(gè)內(nèi)存區(qū)域,在該區(qū)域中劃撥出一部分出來專門存放值類型變量,稱為堆棧,堆棧采用先進(jìn)后出的原則,將值類型變量從區(qū)域的最高地址位開始向低位地址存儲(chǔ),先進(jìn)后出,后進(jìn)先出的管理方式保證了值類型變量在出了作用域后能即使的清除占用的內(nèi)存區(qū)域,由于堆棧速度快,所保存的數(shù)據(jù)一般不太大,這部分一般不需要用戶專門操作. 值類型保存在堆棧匯總, 堆棧有非常高的性能,但對(duì)于所有的變量來說還是不太靈活。通常我們希望使用一個(gè)方法分配內(nèi)存,來存儲(chǔ)一些數(shù)據(jù),并在方法退出后的很長(zhǎng)一段時(shí)間內(nèi)數(shù)據(jù)仍是可以使用的。只要是用new運(yùn)算符來請(qǐng)求存儲(chǔ)空間,就存在這種可能性——例如所有的引用類型。此時(shí)就要使用托管堆。它在垃圾收集器的控制下工作,托管堆(或簡(jiǎn)稱為堆)是系統(tǒng)管理的大內(nèi)存區(qū)域中的另一個(gè)內(nèi)存區(qū)域。要了解堆的工作原理和如何為引用數(shù)據(jù)類型分配內(nèi)存,看看下面的代
碼:
Customer arabel = new Customer();
這行代碼完成了以下操作:首先,分配堆上的內(nèi)存,以存儲(chǔ)Customer實(shí)例(一個(gè)真正的實(shí)例,不只是一個(gè)地址)。然后把變量arabel的值設(shè)置為分配給新Customer對(duì)象的內(nèi)存地址(它還調(diào)
用合適的Customer()構(gòu)造函數(shù)初始化類實(shí)例中的字段,但我們不必?fù)?dān)心這部分)。
Customer實(shí)例沒有放在堆棧中,而是放在內(nèi)存的堆中。如果我們這樣操作:
Customer newaddress = arabel ;
這時(shí)候,newaddress也會(huì)保存在堆棧中,其值和arabel 相同,都是存儲(chǔ)Customer實(shí)例的堆地址. 知道了這些,我們會(huì)發(fā)現(xiàn)這樣一個(gè)問題,如果堆棧中arabel 和newaddress兩個(gè)變量過期銷毀,那堆中保存的Customer對(duì)象會(huì)怎樣?實(shí)際上它仍保留在堆中,一直到程序停止,或垃圾收集器刪除它為止. C#的垃圾收集器如果沒有顯示調(diào)用,會(huì)定時(shí)運(yùn)行并檢查內(nèi)存,刪除沒有任何變量引用的數(shù)據(jù).看起來似乎不錯(cuò),但是想想,垃圾回收器并不是時(shí)時(shí)檢查,它是定時(shí)運(yùn)行,而在這段時(shí)間內(nèi)如果產(chǎn)生大量的過期數(shù)據(jù)駐留在內(nèi)存中..... 那么或許我們可以通過調(diào)用System.GC.Collect(),強(qiáng)迫垃圾收集器在代碼的某個(gè)地方運(yùn)行,System.GC是一個(gè)表示垃圾收集器的.NET基類, Collect()方法則調(diào)用垃圾收集器。但是,這種方式適用的場(chǎng)合很少,(難道銷毀一個(gè)對(duì)象就讓垃圾回收檢查一便內(nèi)存嗎?)例如,代碼中有大量的對(duì)象剛剛停止引用,就適合調(diào)用垃圾收集器。況且垃圾收集器的邏輯不能保證在一次垃圾收集過程中,從堆中刪除所有過期數(shù)據(jù),對(duì)于不受垃圾回收器管理的未托管對(duì)象(例如文件句
柄、網(wǎng)絡(luò)連接和數(shù)據(jù)庫連接),它是無能為力的。那該怎么做呢?
這時(shí)需要制定專門的規(guī)則,確保未托管的資源在回收類的一個(gè)實(shí)例時(shí)釋放。 在定義一個(gè)類時(shí),可以使用兩種機(jī)制來自動(dòng)釋放未托管的資源。這些機(jī)制常常放在一起實(shí)現(xiàn),
因?yàn)槊總€(gè)機(jī)制都為問題提供了略為不同的解決方法。這兩個(gè)機(jī)制是:
● 聲明一個(gè)析構(gòu)函數(shù),作為類的一個(gè)成員 ● 在類中實(shí)現(xiàn)System.IDisposable接口
下面依次討論這兩個(gè)機(jī)制,然后介紹如何同時(shí)實(shí)現(xiàn)它們,以獲得最佳的效果。