亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

正確實現 IDisposable 接口

2019-11-18 16:43:46
字體:
來源:轉載
供稿:網友

正確實現 IDisposable

.NET中用于釋放對象資源的接口是IDisposable,但是這個接口的實現還是比較有講究的,此外還有Finalize和Close兩個函數。

MSDN建議按照下面的模式實現IDisposable接口:

 1 public class Foo: IDisposable
 2 {
 3     public void Dispose()
 4     {
 5        Dispose(true);
 6        GC.SupPRessFinalize(this);
 7     }
 8
 9     protected virtual void Dispose(bool disposing)
10     {
11        if (!m_disposed)
12        {
13            if (disposing)
14            {
15               // Release managed resources
16            }
17 
18            // Release unmanaged resources
19 
20            m_disposed = true;
21        }
22     }
23 
24     ~Foo()
25     {
26        Dispose(false);
27     }
28 
29     private bool m_disposed;
30 }
31 
32
 

在.NET的對象中實際上有兩個用于釋放資源的函數:Dispose和Finalize。Finalize的目的是用于釋放非托管的資源,而Dispose是用于釋放所有資源,包括托管的和非托管的。

 

在這個模式中,void Dispose(bool disposing)函數通過一個disposing參數來區別當前是否是被Dispose()調用。如果是被Dispose()調用,那么需要同時釋放托管和非托管的資源。如果是被~Foo()(也就是C#的Finalize())調用了,那么只需要釋放非托管的資源即可。

 

這是因為,Dispose()函數是被其它代碼顯式調用并要求釋放資源的,而Finalize是被GC調用的。在GC調用的時候Foo所引用的其它托管對象可能還不需要被銷毀,并且即使要銷毀,也會由GC來調用。因此在Finalize中只需要釋放非托管資源即可。另外一方面,由于在Dispose()中已經釋放了托管和非托管的資源,因此在對象被GC回收時再次調用Finalize是沒有必要的,所以在Dispose()中調用GC.SuppressFinalize(this)避免重復調用Finalize。

 

然而,即使重復調用Finalize和Dispose也是不存在問題的,因為有變量m_disposed的存在,資源只會被釋放一次,多余的調用會被忽略過去。

 

因此,上面的模式保證了:

 

1、 Finalize只釋放非托管資源;

2、 Dispose釋放托管和非托管資源;

3、 重復調用Finalize和Dispose是沒有問題的;

4、 Finalize和Dispose共享相同的資源釋放策略,因此他們之間也是沒有沖突的。

 

在C#中,這個模式需要顯式地實現,其中C#的~Foo()函數代表了Finalize()。而在C++/CLI中,這個模式是自動實現的,C++的類析構函數則是不一樣的。

 

按照C++語義,析構函數在超出作用域,或者delete的時候被調用。在Managed C++(即.NET 1.1中的托管C++)中,析構函數相當于CLR中的Finalize()方法,在垃圾收集的時候由GC調用,因此,調用的時機是不明確的。在.NET 2.0的C++/CLI中,析構函數的語義被修改為等價與Dispose()方法,這就隱含了兩件事情:

 

1、 所有的C++/CLI中的CLR類都實現了接口IDisposable,因此在C#中可以用using關鍵字來訪問這個類的實例。

2、 析構函數不再等價于Finalize()了。

 

對于第一點,這是一件好事,我認為在語義上Dispose()更加接近于C++析構函數。對于第二點,Microsoft進行了一次擴展,做法是引入了“!”函數,如下所示:

1 public ref class Foo
2 {
3 public:
4        Foo();
5        ~Foo();       // destructor
6        !Foo();       // finalizer
7 };
8
 

“!”函數(我實在不知道應該怎么稱呼它)取代原來Managed C++中的Finalize()被GC調用。MSDN建議,為了減少代碼的重復,可以寫這樣的代碼:

 1 ~Foo()
 2 {
 3     //釋放托管的資源
 4     this->!Foo();
 5 }
 6 
 7 !Foo()
 8 {
 9     //釋放非托管的資源
10 }
11
 

對于上面這個類,實際上C++/CLI生成對應的C#代碼是這樣的:

 


 1 public class Foo
 2 {
 3     private void !Foo()
 4     {
 5        // 釋放非托管的資源
 6     }
 7 
 8     private void ~Foo()
 9     {
10        // 釋放托管的資源
11        !Foo();
12     }
13 
14     public Foo()
15     {
16     }
17 
18     public void Dispose()
19     {
20        Dispose(true);
21        GC.SuppressFinalize(this);
22     }
23 
24     protected virtual void Dispose(bool disposing)
25     {
26        if (disposing)
27        {
28            ~Foo();
29        }
30        else
31        {
32            try
33            {
34               !Foo();
35            }
36            finally
37            {
38               base.Finalize();
39            }
40        }
41     }
42 
43     protected void Finalize()
44     {
45        Dispose(false);
46     }
47 }
48
 

由于~Foo()和!Foo()不會被重復調用(至少MS這樣認為),因此在這段代碼中沒有和前面m_disposed相同的變量,但是基本的結構是一樣的。

 

并且,可以看到實際上并不是~Foo()和!Foo()就是Dispose和Finalize,而是C++/CLI編譯器生成了兩個Dispose和Finalize函數,并在合適的時候調用它們。C++/CLI其實已經做了很多工作,但是唯一的一個問題就是依賴于用戶在~Foo()中調用!Foo()。

 

關于資源釋放,最后一點需要提的是Close函數。在語義上它和Dispose很類似,按照MSDN的說法,提供這個函數是為了讓用戶感覺舒服一點,因為對于某些對象,例如文件,用戶更加習慣調用Close()。

 

然而,畢竟這兩個函數做的是同一件事情,因此MSDN建議的代碼就是:

 

1 public void Close()
2 {
3     Dispose(();
4 }
5
6
這里直接調用不帶參數的Dispose函數以獲得和Dispose相同的語義。這樣似乎就圓滿了,但是從另外一方面說,如果同時提供了Dispose和Close,會給用戶帶來一些困惑。沒有看到代碼細節的前提下,很難知道這兩個函數到底有什么區別。因此在.NET的代碼設計規范中說,這兩個函數實際上只能讓用戶用一個。因此建議的模式是:

 1 public class Foo: IDisposable
 2 {
 3     public void Close()
 4     {
 5        Dispose();
 6     }
 7 
 8     void IDisposable.Dispose()
 9     {
10        Dispose(true);
11        GC.SuppressFinalize(this);
12     }
13 
14     protected virtual void Dispose(bool disposing)
15     {
16        // 同前
17     }
18 }
19
 

這里使用了一個所謂的接口顯式實現:void IDisposable.Dispose()。這個顯式實現只能通過接口來訪問,但是不能通過實現類來訪問。因此:

 
1 Foo foo = new Foo();
2
3 foo.Dispose(); // 錯誤
4 (foo as IDisposable).Dispose(); // 正確
5


這樣做到了兼顧兩者。對于喜歡使用Close的人,可以直接用 foo.Close(),并且他看不到 Dispose()。對于喜歡Dispose的,他可以把類型轉換為 IDisposable 來調用,或者使用using語句。兩者皆大歡喜!
http://www.49028c.com/xlshcn/archive/2007/01/16/idisposable.html


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品中文字幕视频| 一区二区三区视频免费| 国产精品扒开腿做| 精品久久久一区二区| 亚洲国产高清福利视频| 91在线精品播放| 日本韩国欧美精品大片卡二| 国产精品日韩久久久久| 日韩理论片久久| 国产精品自拍网| 亚洲人成电影在线观看天堂色| 亚洲成人网在线| 国产色婷婷国产综合在线理论片a| 国产精品久久久久久久久影视| 精品国产乱码久久久久久婷婷| 午夜精品久久久久久久99热浪潮| 95av在线视频| 91av在线网站| 久久影视免费观看| 日韩精品电影网| 成人亚洲综合色就1024| 中文字幕少妇一区二区三区| 伊人精品在线观看| 日韩成人在线视频| 亚洲美女视频网站| 国产成人精品综合久久久| 精品视频在线观看日韩| 91国偷自产一区二区三区的观看方式| 日本精品一区二区三区在线| 国产精品爽爽爽爽爽爽在线观看| 国产日韩欧美夫妻视频在线观看| 国产精品久久久久久久久久久不卡| 亚洲综合精品一区二区| 日韩美女写真福利在线观看| 国产日韩换脸av一区在线观看| 欧美老少做受xxxx高潮| 亚洲精品有码在线| 日韩免费高清在线观看| www.亚洲成人| 欧美在线一区二区视频| 成人激情视频免费在线| 久久影视三级福利片| 美女性感视频久久久| 97人人做人人爱| 久久久这里只有精品视频| 亚洲精品自拍偷拍| 日韩精品中文在线观看| 欧美久久精品一级黑人c片| 另类美女黄大片| 亚洲自拍偷拍视频| 国产亚洲精品久久久久动| 菠萝蜜影院一区二区免费| 国产亚洲欧美日韩精品| 国产日韩在线免费| 国产成人精品视频在线观看| 韩国精品久久久999| 久久久国产91| 国产丝袜高跟一区| 国产精品91免费在线| 国产91在线播放精品91| 日本国产一区二区三区| 亚洲激情小视频| 国产精品黄色影片导航在线观看| 操人视频在线观看欧美| 国内精品400部情侣激情| 国产午夜精品一区理论片飘花| 亚洲精品欧美一区二区三区| 国产精品福利无圣光在线一区| 国产精品无av码在线观看| 九九久久精品一区| 国产日韩欧美黄色| 国产精品视频大全| 日韩av免费一区| 久久精品中文字幕电影| 日本欧美国产在线| 日韩精品在线视频美女| 欧美一级免费视频| 成人美女av在线直播| 久久色免费在线视频| 亚洲欧美福利视频| 久久精品成人欧美大片古装| 国产精品一区=区| 国产亚洲精品91在线| 亚洲人成电影网站色www| 自拍偷拍亚洲区| 久色乳综合思思在线视频| 色777狠狠综合秋免鲁丝| 国产精品一区久久| 久久久久久久色| 色99之美女主播在线视频| 欧美日韩另类在线| 国产99视频精品免视看7| 国产国语videosex另类| 国产精品吹潮在线观看| 欧美精品在线第一页| 97在线精品国自产拍中文| 欧美激情视频网站| 久久综合久久88| 日韩欧美亚洲一二三区| 亚洲尤物视频网| 久久久久久久久久久91| www.日本久久久久com.| 国产精品444| 欧美午夜xxx| 欧美在线观看一区二区三区| 欧美激情视频给我| 三级精品视频久久久久| 国内揄拍国内精品少妇国语| 久久的精品视频| 97久久精品人搡人人玩| 亚洲情综合五月天| 国产精品视频网址| 亚洲第一网站免费视频| 亚洲美女中文字幕| 国产福利精品视频| 亚洲精品国精品久久99热| 国产精品pans私拍| 亚洲国产成人爱av在线播放| 国产97色在线| 日韩成人av网| 日韩经典中文字幕在线观看| 国产精品影片在线观看| 欧美精品久久久久| 久久91精品国产| 96pao国产成视频永久免费| 国产欧美日韩视频| 色婷婷综合成人| 国内精品视频久久| 欧美精品久久久久久久免费观看| 日韩久久免费视频| 国产精品视频一区国模私拍| 九九热这里只有精品6| 国产日韩精品在线| 亚洲人永久免费| 欧美亚洲国产视频| 萌白酱国产一区二区| 欧美大胆在线视频| 国产成人在线一区| 国产日本欧美在线观看| 亚洲国产精品va在线看黑人动漫| 日韩大陆欧美高清视频区| 91精品久久久久久久久久入口| 国内揄拍国内精品| 精品一区二区三区三区| 日韩欧美在线视频日韩欧美在线视频| 色综合五月天导航| 久久久久久国产精品三级玉女聊斋| 神马国产精品影院av| 久久69精品久久久久久国产越南| 一区二区三区 在线观看视| 国产成人精品电影久久久| 中文字幕久精品免费视频| 欧美综合激情网| 九九久久久久久久久激情| 国产精品久久久久高潮| 人九九综合九九宗合| 96国产粉嫩美女| 国产精品老女人视频| 国产精品69久久久久| 国产91色在线播放| 欧美日韩亚洲网| 亚洲福利视频网站| 欧美一级成年大片在线观看| 国产九九精品视频|