C# Finalize和Dispose的区别

一:总结php

一、Finalize方法(C#中是析构函数,如下称析构函数)是用于释放非托管资源的,而托管资源会由GC自动回收。因此,咱们也能够这样来区分 托管和非托管资源。全部会由GC自动回收的资源,就是托管的资源,而不能由GC自动回收的资源,就是非托管资源。在咱们的类中直接使用非托管资源的状况很 少,因此基本上不用咱们写析构函数。

二、大部分的非托管资源会给系统带来不少负面影响,例如数据库链接不被释放就可能致使链接池中的可用数据库链接用尽。文件不关闭会致使其它进程没法读写这个文件等等。

实现模型:
一、因为大多数的非托管资源都要求能够手动释放,因此,咱们应该专门为释放非托管资源公开一个方法。实现IDispose接口的Dispose方法是最好的模型,由于C#支持using语句快,能够在离开语句块时自动调用Dispose方法。

二、虽然能够手动释放非托管资源,咱们仍然要在析构函数中释放非托管资源,这样才是安全的应用程序。不然若是由于程序员的疏忽忘记了手动释放非托管资源, 那么就会带来灾难性的后果。因此说在析构函数中释放非托管资源,是一种补救的措施,至少对于大多数类来讲是如此。

三、因为析构函数的调用将致使GC对对象回收的效率下降,因此若是已经完成了析构函数该干的事情(例如释放非托管资源),就应当使用SuppressFinalize方法告诉GC不须要再执行某个对象的析构函数。

四、析构函数中只能释放非托管资源而不能对任何托管的对象/资源进行操做。由于你没法预测析构函数的运行时机,因此,当析构函数被执行的时候,也许你进行操做的托管资源已经被释放了。这样将致使严重的后果。

五、(这是一个规则)若是一个类拥有一个实现了IDispose接口类型的成员,并建立(注意是建立,而不是接收,必须是由类本身建立)它的实例对象,则 这个类也应该实现IDispose接口,并在Dispose方法中调用全部实现了IDispose接口的成员的Dispose方法。
只有这样的才能保证全部实现了IDispose接口的类的对象的Dispose方法可以被调用到,确保能够手动释听任何须要释放的资源。程序员

 

二:实现 Finalize 和 Dispose 以清理非托管资源

http://msdn.microsoft.com/zh-cn/library/b1yfkh5e(VS.80).aspx数据库

 

http://www.sudu.cn/info/index.php?op=article&id=12170c#

三:维护内部非托管资源的托管类的手段:Finalize()--终结Dispose()--处置安全

非托管资源:原始的操做系统文件句柄,原始的非托管数据库链接,非托管内存或其余非托管资源。ide

Finalize()特性:函数

  • 重写Finalize()的惟一缘由是,c#类经过PInvoke或复杂的COM互操做性任务使用了非托管资源(典型的状况是经过System.Runtime.InteropServices.Marshal类型定义的各成员)注:PInvoke是平台调用服务。
  • object中有finalize方法,但建立的类不能重写此方法,若Overide会报错,只能经过析构函数来达到一样的效果。
  • Finalize方法的做用是保证.NET对象能在垃圾回收时清除非托管资源。
  • 在CLR在托管堆上分配对象时,运行库自动肯定该对象是否提供一个自定义的Finalize方法。若是是这样,对象会被标记为可终结的,同时一个指向这个对象的指针被保存在名为终结队列的内部队列中。终结队列是一个由垃圾回收器维护的表,它指向每个在从堆上删除以前必须被终结的对象。
  • 注意:Finalize虽然看似手动清除非托管资源,其实仍是由垃圾回收器维护,它的最大做用是确保非托管资源必定被释放
  • 在结构上重写Finalize是不合法的,由于结构是值类型,不在堆上,Finalize是垃圾回收器调用来清理托管堆的,而结构不在堆上。

Dispose()特性:编码

  • 为了更快更具操做性进行释放,而非让垃圾回收器(即不可预知)来进行,可使用Dispose,即实现IDispose接口.
  • 结构和类类型均可以实现IDispose(与重写Finalize不一样,Finalize只适用于类类型),由于不是垃圾回收器来调用Dispose方法,而是对象自己释放非托管资源,如Car.Dispose().若是编码时没有调用Dispose方法,觉得着非托管资源永远得不到释放。
  • 若是对象支持IDisposable,老是要对任何直接建立的对象调用Dispose(),即有实现IDisposable接口的类对象都必须调用Dispose方法。应该认为,若是类设计者选择支持Dispose方法,这个类型就须要执行清除工做。记住一点,若是类型实现了IDisposable接口,调用Dispose方法老是正确的。
  • .net基类库中许多类型都实现IDisposable接口,并使用了Dispose的别名,其中一个别名如IO中的Close方法,等等别名。使得看起来更天然。
  • using关键字,实际内部也是实现IDisposable方法,用ildasm.exe查看使用了using的代码的CIL,会发现是用try/finally去包含using中的代码,而且在finally中调用dispose方法。

我的总结:spa

相同点:操作系统

  • 都是为了确保非托管资源获得释放。

不一样点:

  • finalize由垃圾回收器调用;dispose由对象调用。
  • finalize无需担忧由于没有调用finalize而使非托管资源得不到释放,而dispose必须手动调用。
  • finalize虽然无需担忧由于没有调用finalize而使非托管资源得不到释放,但由于由垃圾回收器管理,不能保证当即释放非托管资源;而dispose一调用便释放非托管资源。
  • 只有类类型才能重写finalize,而结构不能;类和结构都能实现IDispose.缘由请看Finalize()特性