A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© aisini 金牌黑马   /  2014-8-26 09:10  /  942 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

        当我们开发C#代码的时候,经常碰到一个问题,有些class提供Close(),有些class提供Dispose(),那么Dispose和Close到底有什么区别?
        首先,Dispose和Close基本上应该是一样的。Close是为了那些不熟悉Dispose的开发者设计的。因为基本上所有的developer都知道Close是干吗的(特别是对于那些有C++背景的developer)。
         但是当我们写code时候,如果要实现Close和Dispose的时候,要注意Close和Dispose的设计模式。.net的一些class只提供Close,而且派生自IDisposable,并且隐藏了Dispose方法。是不是觉得很不明白了?
        对这些class来说,关键在于它们显式的(explicitly)实现了IDisposable。对于隐式实现来说,你只需要调用"new A().Dispose()",但是对于显式实现来说Dispose不会是这个class的成员函数。唯一的调用方式是你先要cast到 IDisposable才行。(“new A().Dispose()”编译不过,但是“((IDisposable)newA()).Dispose()”可以编译过)。所以这样就符合了设计的要求:提供Close(),隐藏Dispose(),并且实现了 IDisposable接口。
          在.net的framework里,Close()被设计成public的,并且在Close()里面call被隐藏的Dispose(); Dispose()去call另一个virtual的Dispose(bool)函数。所以如果你从这个class继承,你就必须实现Dispose (bool)方法。
        调用者call Close()的时候就会call到你重载的那个Dispose(bool)方法去释放资源。
请参考 http://blogs.msdn.com/brada/archive/2003/07/06/50127.aspx
注意事项:
1,Close()不应该被定义成virtual。对于这个design pattern,Close()只是用来call那个隐藏的Dispose(),用户不应该改变Close的behavior。对于这个问题, System.IO.Stream也有设计问题。之所以有问题是为了满足向后兼容的需求。See http://msdn2.microsoft.com/en-us/library/ms227422.aspx. 文档里面提到虽然Close()是virtual的,但是不应该被override。
  1. </blockquote></div><div class="blockcode"><blockquote>using System;

  2. namespace ConsoleApplication
  3. {
  4.   abstract class MyStream : IDisposable
  5.     {
  6.          public MyStream()
  7.          {
  8.              m_unmanagedResource = Marshal.AllocCoTaskMem(100);
  9.             m_bitmap = new Bitmap(50, 50);
  10.         }

  11.          #region IDisposable Members
  12.        void IDisposable.Dispose()
  13.          {
  14.              Dispose(true);
  15.             GC.SuppressFinalize(this);
  16.          }

  17.          protected virtual void Dispose(bool isDisposing)
  18.          {
  19.              if (!m_disposed)
  20.              {
  21.                  if (isDisposing)
  22.                  {
  23.                      m_bitmap.Dispose();
  24.                 }
  25.                  Marshal.FreeCoTaskMem(m_unmanagedResource);
  26.                  m_disposed = true;
  27.              }
  28.          }
  29.          
  30.          public void Close()
  31.          {
  32.              ((IDisposable)this).Dispose();
  33.          }

  34.          ~MyStream()
  35.          {
  36.              Dispose(false);            
  37.          }

  38.          private IntPtr m_unmanagedResource;     // Unmanaged resource
  39.          private Bitmap m_bitmap;                // IDisposable managed resources
  40.          private bool m_disposed;
  41.          
  42.          #endregion
  43.      }

  44.      class MyDerivedStream : MyStream
  45.      {
  46.          public MyDerivedStream()
  47.          {
  48.              m_anotherMemory = Marshal.AllocCoTaskMem(20);
  49.             m_anotherImage = new Bitmap(24, 24);
  50.          }

  51.          protected override void Dispose(bool isDisposing)
  52.          {
  53.              if (!m_disposed)
  54.              {
  55.                  if (isDisposing)
  56.                  {
  57.                      m_anotherImage.Dispose();
  58.                  }

  59.                  Marshal.FreeCoTaskMem(m_anotherMemory);
  60.                  base.Dispose(isDisposing);
  61.                  m_disposed = true;
  62.              }
  63.          }

  64.          public static void Main(string[] args)
  65.          {
  66.              MyStream aStream = new MyDerivedStream();

  67.              aStream.Close();          // Allowed
  68.              // aStream.Dispose();    // Cannot compile

  69.              ((IDisposable)aStream).Dispose();     // Allowed

  70.              //
  71.              //  This one works as well, because newStream calls the explicit implemented
  72.              //  IDisposable.Dispose method
  73.              //
  74.              using (MyStream newStream = new MyDerivedStream())
  75.              {
  76.                  //
  77.                  //  Do something
  78.                  //
  79.              }
  80.          }
  81.          
  82.          private IntPtr m_anotherMemory;
  83.          private Bitmap m_anotherImage;
  84.          private bool m_disposed;
  85.      }
  86. }
复制代码



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马