当前位置:首页 > 网络编程 > WEB编程 > ASP.net >  正确实现 IDisposable 接口2

 正确实现 IDisposable 接口2

点击次数:25 次 发布日期:2008-11-26 11:36:17 作者:源代码网
源代码网推荐      对于第一点,这是一件好事,我认为在语义上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.cnblogs.com/xlshcn/archive/2007/01/16/idisposable.html
源代码网推荐    做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。
源代码网推荐


源代码网供稿.
网友评论 (0)
会员中心
网络编程
本站推荐
网络编程之精华