C#资源释放及Dispose、Close和析构方法

发表于:2012-6-01 09:38

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Luminji    来源:51Testing软件测试网采编

  一:什么是资源

  在开始本文前,需要一些准备知识。首先要提出“什么是资源”。在CLR出来之后,Windows系统资源开始分为“非托管资源”和“托管资源”。

  非托管资源是指:所有的Window内核对象(句柄)都是非托管资源,如对于Stream,数据库连接,GDI+的相关对象,还有Com对象等等,这些资源并不是受到CLR管理;

  托管资源是指:由CLR管理分配和释放的资源,即由CLR里new出来的对象。

  其次再来讲,资源的释放方式。

  非托管资源:需要显式释放的,也即需要你写代码释放;

  托管资源:并不需要显式释放,但是如果引用类型本身含有非托管资源,则需要进行现实释放;

  二:显式释放的C#实现

  显式释放的C#实现,由C#语法支持的有:

  1:实现IDisposable接口的Dispose方法;

  2:析构方法(终结器);

  不由C#语法支持,但是约定支持的显式释放是:

  3:提供显示释放方法,比如常用的Close方法;

  三:Dispose、Close和析构方法异同点

  但是,还需要区分这3种方式的异同点。首先,你无法调用析构方法。析构方法是由垃圾回收机制进行调用的。换句话来说,就是你不知道析构方法被调用的时机。严格意义上来说,它只是作为资源释放的一个补救措施。

  资源释放的一个正确的措施是为类型实现IDisposable接口的Dispose。当你需要释放类型的资源的时候,应该显示的调用Dipose方法。当然,这里还有一个C#的语法糖,就是使用using程序块,在离开using程序块的时候,CLR会自动调用类型所创建对象的Dipose方法。

  可能有人会问道,既然可以通过Dispose方法的方式来进行资源的释放,为什么有些类型还需要提供一个Close方法。这里面的区别,或者说约定在于,如果你仔细观察这些类型:他们基本都只公开了Close方法,他们都实现了IDisposable,但都隐藏了Dispose方法。以Socket这个类为例,它:

  1:提供public void Close()

publicvoidClose()
{
           
//….
            ((IDisposable)this).Dispose();
           
//….
        }

  2:提供显式void IDisposable.Dispose()

voidIDisposable.Dispose()
        {
           
this.Dispose(true);
            GC.SuppressFinalize(
this);
        }

  3:提供protected virtual void Dispose(bool disposing)。真正的资源释放的代码放在这里。

  所以理论上来将,提供Close方法最终还是使用的Dispose方法,之所以这么做,是因为这些类型出于显式实现IDisposable的因素,在调用这些Dispose方法的时候,必须完成一次转型,如:

  ((IDisposable)new A()).Dispose();

  为了避免转型,同时也为了避免不熟悉C#语法的开发人员更直观的释放资源,提供了Close方法。

  在上文的例子中,你可能已经注意到IDisposable.Dispose这个方法中,包含一句:

  GC.SuppressFinalize(this);

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号