All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
在Asp.net中为图像加入版权信息_[Asp.Net教程]
不使用VS进行ASP.NET,Membership管理_[Asp.Net教程]
Visual C++向对话框类中添加工具栏
ASP.NET中MD5和SHA1加密的几种方法_.net资料_编程技术
visual c++手工添加消息处理函数
AJAX入门之XMLHttpRequest慨述_[AJAX教程]
在ASP.NET代码里访问跟踪信息_.net资料_编程技术
制作WEB在线编辑器-插入HTML标签_.net资料_编程技术
如何在Asp.net中使用HtmlArea编辑器_[Asp.Net教程]
入门:Windows环境下PHP动态网页配置详解_php资料_编程技术
Reading number is top 10 pictures
Beauty Sun Feifei
10 powerless things in life
Soong ching ling's former residence2
Ashlynn Brooke show proud chest measurement2
From China fortress sora aoi4
A man's favorite things6
The hot big eye big breast beauty3
The world's ten biggest attractions of inventory super the moon
人物写真-谢楠
Li Zongrui hunting video screenshots2
Download software ranking
塘西风月痕
Unix video tutorial5
传奇私服架设教程
尖东毒玫瑰A
The hero
天龙八部最新服务端
WebService在.NET中的实战应用教学视频 → 第3集
小黑猫大战两米大花蛇
matrix2
Boxer vs Yellow2
delv published in(发表于) 2014/1/10 6:32:15 Edit(编辑)
正确实现,IDisposable,接口_[Asp.Net教程]

正确实现,IDisposable,接口_[Asp.Net教程]

正确实现 IDisposable 接口_[Asp.Net教程]


正确实现 IDisposable


.NET中用于释放对象资源的接口是IDisposable,但是这个接口的实现还是比较有讲究的,此外还有Finalize和Close两个函数。


MSDN建议按照下面的模式实现IDisposable接口:


1 public class Fo 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 Fo 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.cnblogs.com/xlshcn/archive/2007/01/16/idisposable.html







添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.