C#中標(biāo)準(zhǔn)的IDispose模式代碼詳解
C#實(shí)現(xiàn)IDispose接口
.net的GC機(jī)制有兩個(gè)問(wèn)題:首先GC并不能釋放所有資源,它更不能釋放非托管資源。其次,GC也不是實(shí)時(shí)的,所有GC存在不確定性。
為了解決這個(gè)問(wèn)題donet提供了析構(gòu)函數(shù)
public class TestClass : System.IDisposable
{
//供程序員顯式調(diào)用的Dispose方法
public void Dispose()
{
//調(diào)用帶參數(shù)的Dispose方法,釋放托管和非托管資源
Dispose(true);
//手動(dòng)調(diào)用了Dispose釋放資源,那么析構(gòu)函數(shù)就是不必要的了,這里阻止GC調(diào)用析構(gòu)函數(shù)
System.GC.SuppressFinalize(this);
}
//protected的Dispose方法,保證不會(huì)被外部調(diào)用。
//傳入bool值disposing以確定是否釋放托管資源
protected void Dispose(bool disposing)
{
if (disposing)
{
///TODO:在這里加入清理"托管資源"的代碼,應(yīng)該是xxx.Dispose();
}
///TODO:在這里加入清理"非托管資源"的代碼
}
//供GC調(diào)用的析構(gòu)函數(shù)
~TestClass()
{
Dispose(false);//釋放非托管資源
}
}
而即使我們忘記了在合適的時(shí)候調(diào)用Dispose,GC也會(huì)在釋放對(duì)象的時(shí)候幫我們清理非托管資源的。GC所充當(dāng)?shù)慕巧皇且环N保障手段,它應(yīng)該充當(dāng)這種角色,我們不能過(guò)分依賴它。實(shí)際上,在較大的模塊退出時(shí)我們還應(yīng)該及時(shí)地手動(dòng)調(diào)用GC.Collect進(jìn)行垃圾回收。
為什么實(shí)現(xiàn)IDisposable接口的類(lèi)的對(duì)象,因?yàn)?net CLR是采用GC(垃圾回收器)機(jī)制管理內(nèi)存,不想C++語(yǔ)言那樣,能保證對(duì)象的析構(gòu)函數(shù)在作用域結(jié)束時(shí)被總是被自動(dòng)調(diào)用,有時(shí)如果程序運(yùn)行的過(guò)程中一直沒(méi)有滿足啟動(dòng)GC的條件,則可能GC一次也沒(méi)啟動(dòng)。 這樣,如果一個(gè)類(lèi)需要占用重要資源,就應(yīng)該實(shí)現(xiàn)IDisposable接口,或者使用另一種簡(jiǎn)捷的方式:使用Using,如:
Using(MyClass myObj = new MyClass())
{ ... }
對(duì)于沒(méi)有實(shí)現(xiàn)IDisposable接口的,也就沒(méi)什么Dispose方法,但他們的Finalize同樣不能保證被調(diào)用。
Using(MyClass myObj = new MyClass())
{ ... }
是一種好方法,但是只有MyClass實(shí)現(xiàn)了IDisposable接口才能這樣寫(xiě).
IDispose模式在C++中用的很多,用來(lái)清理資源,而在C#里,資源分為托管和非托管兩種,托管資源是由C#的CLR幫助我們清理的,它是通過(guò)調(diào)用對(duì)象的析構(gòu)函數(shù)完成的對(duì)象釋放工作,而對(duì)于非托管系統(tǒng)來(lái)說(shuō),則需要我們自己來(lái)釋放,例如數(shù)據(jù)庫(kù)連接對(duì)象,這就需要我們手動(dòng)去調(diào)用它的Dispose()方法來(lái)實(shí)現(xiàn)對(duì)象它的釋放,事實(shí)上,Dispose()內(nèi)容到底做了什么事,我們并不清楚,當(dāng)然這就是面向?qū)ο?,它不希望你關(guān)系實(shí)現(xiàn)的細(xì)節(jié),呵!
對(duì)于我們開(kāi)發(fā)人員來(lái)說(shuō),在了解它怎么用之后,總會(huì)對(duì)它如何實(shí)現(xiàn)的產(chǎn)生興趣,下面,我將把C#里實(shí)現(xiàn)IDispose模式的代碼展現(xiàn)出來(lái),大家一起來(lái)學(xué)習(xí)一下,事實(shí)上,它的使用場(chǎng)合也很多的,當(dāng)我們手動(dòng)對(duì)網(wǎng)站,數(shù)據(jù)庫(kù)作封裝時(shí),都會(huì)用的到,下面看一下代碼:
/// <summary>
/// 實(shí)現(xiàn)IDisposable,對(duì)非托管系統(tǒng)進(jìn)行資源回收
/// </summary>
public class IDisplosePattern : IDisposable
{
public void Dispose()
{
this.Dispose(true);////釋放托管資源
GC.SuppressFinalize(this);//請(qǐng)求系統(tǒng)不要調(diào)用指定對(duì)象的終結(jié)器. //該方法在對(duì)象頭中設(shè)置一個(gè)位,系統(tǒng)在調(diào)用終結(jié)器時(shí)將檢查這個(gè)位
}
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)//_isDisposed為false表示沒(méi)有進(jìn)行手動(dòng)dispose
{
if (disposing)
{
//清理托管資源
}
//清理非托管資源
}
_isDisposed = true;
}
private bool _isDisposed;
~IDisplosePattern()
{
this.Dispose(false);//釋放非托管資源,托管資源由終極器自己完成了
}
}
通過(guò)上面的代碼,我們知道了,對(duì)于托管系統(tǒng)(C#的CLR為我們管理的),直接通過(guò)~IDisplosePattern()方法進(jìn)行釋放,而~IDisplosePattern()這個(gè)方法何時(shí)被調(diào)用,我們是不知道的,因?yàn)樗怯蒀LR幫助我們調(diào)用的,而我們手動(dòng)進(jìn)行dispose方法時(shí),它會(huì)調(diào)用dispose(true)這個(gè)重載方法,它會(huì)幫助我們清理托管和非托管資源,如圖:

以上就是本次介紹的全部知識(shí)點(diǎn)內(nèi)容,感謝大家的學(xué)習(xí)和對(duì)腳本之家的支持。
相關(guān)文章
C# 動(dòng)態(tài)輸出Dos命令執(zhí)行結(jié)果的實(shí)例(附源碼)
這篇文章主要介紹了C# 動(dòng)態(tài)輸出Dos命令執(zhí)行結(jié)果的實(shí)例,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07
關(guān)于C#操作文件路徑(Directory)的常用靜態(tài)方法詳解
這篇文章主要給大家介紹了關(guān)于C#操作文件路徑(Directory)的常用靜態(tài)方法,Directory類(lèi)位于System.IO 命名空間,Directory類(lèi)提供了在目錄和子目錄中進(jìn)行創(chuàng)建移動(dòng)和列舉操作的靜態(tài)方法,需要的朋友可以參考下2021-08-08
關(guān)于C#基礎(chǔ)知識(shí)回顧--反射(三)
在前面例子中,由于MyClass類(lèi)型的對(duì)象是顯示創(chuàng)建的,因此使用反射技術(shù)來(lái)調(diào)用MyClass上的方法沒(méi)有任何優(yōu)勢(shì)--以普通的方式調(diào)用對(duì)象上的方法會(huì)簡(jiǎn)單的多2013-07-07
C#中泛型容器Stack<T>的用法并實(shí)現(xiàn)”撤銷(xiāo)/重做”功能
這篇文章介紹了C#中泛型容器Stack<T>的用法并實(shí)現(xiàn)”撤銷(xiāo)/重做”功能,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-10-10
C#利用RabbitMQ實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)消息傳輸
RabbitMQ做為消息代理,負(fù)責(zé)接收和轉(zhuǎn)發(fā)消息,可以將RabbitMQ比喻為一個(gè)郵筒、一個(gè)郵局和一個(gè)郵遞員。本文主要以一個(gè)簡(jiǎn)單的小例子,簡(jiǎn)述RabbitMQ實(shí)現(xiàn)消息傳輸?shù)南嚓P(guān)內(nèi)容,僅供學(xué)習(xí)分享使用,如有不足之處,還請(qǐng)指正。2021-05-05
C# 設(shè)置防火墻的創(chuàng)建規(guī)則
這篇文章主要介紹了C# 設(shè)置防火墻的創(chuàng)建規(guī)則,幫助大家更好的利用c#操作防火墻,感興趣的朋友可以了解下2020-11-11

