热门:网页模板.net视频教程JQueryMVCjsonExtJs源码示例三级联动JQuery菜单
您现在的位置:.Net中文社区>> .Net编程>>正文内容

详解Close()和Dispose()的区别!

发布时间:2010年03月04日点击数: 佚名

很多人都认为Close()方法内部会调用Dispose()方法,所以并没有本质的区别!实际上这个看法不是很准确,对有些类来说,的确Close()和Dispose()没有本质区别,但是对有些类来说并非如此!
首先,让我们看看我们最常使用的SqlConnection的Close()方法和Dispose()方法的区别:
SqlConnection类的Dispose()方法是继承于Component类的,源代码是这样的:
 

  1. public void Dispose() {   
  2.             Dispose(true); //调用Dispose的一个带参数的重载  
  3.             GC.SuppressFinalize(this);  //请求系统不要调用指定对象的终结器。  
  4.         }  
  5.         protected virtual void Dispose(bool disposing) {  
  6.             if (disposing) {   
  7.                 lock(this) {  
  8.                     if (site != null && site.Container != null) {  
  9.                         site.Container.Remove(this);  
  10.                     }   
  11.                     if (events != null) {  
  12.                         EventHandler handler = (EventHandler)events[EventDisposed];   
  13.                         if (handler != null) handler(this, EventArgs.Empty);   
  14.                     }  
  15.                 }   
  16.             }  
  17.         }  

SqlConnection类的Close()方法在MSDN中的说明是这样的:
关闭与数据库的连接。这是关闭任何打开连接的首选方法。 如果 SqlConnection 超出范围,则不会将其关闭。因

此,必须通过调用 Close 或 Dispose 显式关闭该连接。Close 和 Dispose 在功能上等效。如果连接池值

Pooling 设置为 true 或 yes,则基础连接将返回到连接池。另一方面,如果 Pooling 设置为 false 或 no,则

会关闭到服务器的基础连接。
看说明好象是Close()方法和Dispose()方法是类似的,实际上只是在关闭连接这个功能上等效,让我们看看Close

()方法的源代码:
 

  1.  override public void Close() {   
  2.             IntPtr hscp;  
  3.             Bid.ScopeEnter(out hscp, "<sc.SqlConnection.Close|API> %d#" , ObjectID);   
  4.             try {  
  5.                 SqlStatistics statistics = null;  
  6.  
  7.                 RuntimeHelpers.PrepareConstrainedRegions();   
  8.                 try {
  9. #if DEBUG   
  10.                     object initialReliabilitySlotValue = Thread.GetData(TdsParser.ReliabilitySlot);   
  11.  
  12.                     RuntimeHelpers.PrepareConstrainedRegions();   
  13.                     try {  
  14.                         Thread.SetData(TdsParser.ReliabilitySlot, true);
  15. #endif //DEBUG  
  16.                         statistics = SqlStatistics.StartTimer(Statistics);   
  17.  
  18.                         // The lock here is to protect against the command.cancel / connection.close   
  19.  
  20. race condition   
  21.                         // The SqlInternalConnectionTds is set to OpenBusy during close, once this   
  22.  
  23. happens the cast below will fail and   
  24.                         // the command will no longer be cancelable.  It might be desirable to be   
  25.  
  26. able to cancel the close opperation, but this is 
  27.                         // outside of the scope of Whidbey RTM.  See (SqlCommand::Cancel) for other   
  28.  
  29. lock.   
  30.                         lock (InnerConnection) {  
  31.                             InnerConnection.CloseConnection(this, ConnectionFactory);  
  32.                         }  
  33.                         // does not require GC.KeepAlive(this) because of OnStateChange   
  34.  
  35.                         if (null != Statistics) {   
  36.                             ADP.TimerCurrent(out _statistics._closeTimestamp);   
  37.                         }
  38.  #if DEBUG   
  39.                     }  
  40.                     finally {  
  41.                         Thread.SetData(TdsParser.ReliabilitySlot, initialReliabilitySlotValue);  
  42.                     } 
  43. #endif //DEBUG  
  44.                 }   
  45.                 catch (System.OutOfMemoryException e) {   
  46.                     Abort(e);  
  47.                     throw;   
  48.                 }  
  49.                 catch (System.StackOverflowException e) {  
  50.                     Abort(e);  
  51.                     throw;   
  52.                 }  
  53.                 catch (System.Threading.ThreadAbortException e) {   
  54.                     Abort(e);   
  55.                     throw;  
  56.                 }   
  57.                 finally {  
  58.                     SqlStatistics.StopTimer(statistics);  
  59.                 }  
  60.             }   
  61.             finally {  
  62.                 SqlDebugContext  sdc = _sdc;   
  63.                 _sdc = null;   
  64.                 Bid.ScopeLeave(ref hscp);  
  65.                 if (sdc != null) {   
  66.                    sdc.Dispose();  
  67.                 }  
  68.             }  
  69.         }   

可以看到Close()方法并没有调用Dispose()方法,虽然有一行sdc.Dispose();,但是这只是释放SqlDebugContext

实例,和SqlConnection.Dispose()方法没有关系!

那么区别在哪里呢?
Close()方法只是关闭了连接,然后这个连接被存储到连接池,所以在调用Close()方法以后,还是可以再通过

Open()方法来打开连接的
而调用Dispose()方法以后,这个连接就不能在使用了!
还有一个重要区别就是,当Close()方法并没有调用GC.SuppressFinalize(this);,这导致的直接后果就是在垃圾

回收的时候需要进行终止化操作,这会导致这个实例的“代龄”提升,从而极大的延迟这个对象的回收时间!

针对SqlConnection这个类来说,如果以后还需要使用这个连接可以使用Close()方法临时关闭连接,如果以后不需

要使用这个连接了,可以优先选用Dispose()方法来释放资源,当然你可以使用using关键字来简化这个过程,

OleDbConnection类和OdbcConnection类的源代码我没有找到,但是应该和SqlConnection类是类似的!

让我们在看一个我们常用的类,看看FileStream类的Close()方法和Dispose()方法有什么区别:
FileStream类的Close()方法是继承于Stream类的,源代码是这样的:

  1. public virtual void Close()   
  2.        {  
  3.            Dispose(true);   
  4.            GC.SuppressFinalize(this);  
  5.        }  
  6. ileStream类的Dispose()方法是继承于Stream类的,源代码是这样的:  
  7.        public void Dispose()   
  8.        {  
  9.            Close();   
  10.        }  

是一个标准的Dispose模式的实现,Close()方法调用的是带参数的Dispose方法,然后调用GC.SuppressFinalize

(this);请求系统不要调用指定对象的终结器。而Dispose()方法直接调用Close()方法!
对于FileStream类来说,Close()方法和Dispose()方法是没有区别!

本站热点业务

更多模板/案例展示

关于我们 | 联系我们 | 团队日志 | 网站地图 | 网站合作