一:总结

1、Finalize方法(C#中是析构函数,以下称析构函数)是用于释放非托管资源的,而托管资源会由GC自动回收。所以,我们也可以这样来区分 托管和非托管资源。所有会由GC自动回收的资源,就是托管的资源,而不能由GC自动回收的资源,就是非托管资源。在我们的类中直接使用非托管资源的情况很 少,所以基本上不用我们写析构函数。

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

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

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

3、由于析构函数的调用将导致GC对对象回收的效率降低,所以如果已经完成了析构函数该干的事情(例如释放非托管资源),就应当使用SuppressFinalize方法告诉GC不需要再执行某个对象的析构函数。

4、析构函数中只能释放非托管资源而不能对任何托管的对象/资源进行操作。因为你无法预测析构函数的运行时机,所以,当析构函数被执行的时候,也许你进行操作的托管资源已经被释放了。这样将导致严重的后果。

5、(这是一个规则)如果一个类拥有一个实现了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=12170

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

非托管资源:原始的操作系统文件句柄,原始的非托管数据库连接,非托管内存或其他非托管资源。

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方法。

个人总结:

相同点:

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

不同点:

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

C# Finalize和Dispose的区别的更多相关文章

  1. 关于C#的垃圾回收机制,Finalize和Dispose的区别(自认为很清晰了,有疑问的评论)

    来到个新地方,新学习C#,前面看到C#的垃圾回收,Finalize和Dispose时,总是一知半解,迷迷糊糊.这次好了,前面连续两次面试问到这个问题,脑子里不是很清晰,加上用英文来表达,更是雪上加霜的 ...

  2. Finalize和Dispose的区别

    https://www.cnblogs.com/Jessy/articles/2552839.html

  3. Close与Dispose的区别

    Close与Dispose的区别: Close 是停业整顿,停业了,可以通过公关,再重开,物还是原来的物:只是关闭而已,没有释放真正的释放资源,可以重新打开:Close是关门Dispose是破产: D ...

  4. C# Note29: Close()和Dispose()的区别

    待更! 深入解析Close()和Dispose()的区别

  5. Finalize()、Dispose()、SafeHandle、GC

    Finalize https://msdn.microsoft.com/en-us/library/system.object.finalize%28v=vs.110%29.aspx https:// ...

  6. Environment.Exit(0) 、Application.Exit() 、this.Close() 、this.Dispose()的区别

    Application.Exit:通知winform消息循环退出.程序会等待所有的前台线程终止后才能真正退出.是一种强行退出方式,就像 Win32 的 PostQuitMessage().它意味着放弃 ...

  7. 深入解析Close()和Dispose()的区别

    很多人都认为Close()方法内部会调用Dispose()方法,所以并没有本质的区别!实际上这个看法不是很准确,对有 些类来说,的确Close()和Dispose()没有本质区别,但是对有些类来说并非 ...

  8. using(){},Close(),Dispose()的区别

    //用Close(),Dispose()方式关闭连接 string connString = "Data Source=(local);Initial Catalog=Linq;Integr ...

  9. Java之final、finalize、finally的区别

    一.性质不同(1)final为关键字:(2)finalize()为方法:(3)finally为为区块标志,用于try语句中:二.作用(1)final为用于标识常量的关键字,final标识的关键字存储在 ...

随机推荐

  1. 2种方式解决vue路由跳转未匹配相应路由避免出现空白页面或者指定404页面

    https://www.cnblogs.com/goloving/p/9254084.html https://www.cnblogs.com/goloving/p/9254084.html 1.路由 ...

  2. DAX/PowerBI系列 - 玩转阿里云 Alicloud Pricing

    DAX/PowerBI系列 - 玩转 阿里云主机 Ali Cloud ECS 难度: ★★☆☆☆(1星) 适用范围: ★★★☆☆(3星) 欢迎交流与骚扰 这是啥: 双十一就到了,码农门,程序猿们有没有 ...

  3. PHP知识点

    目录 1. PHP函数前面添加@的作用 2. PHP连接MySQL数据库字符集设置 1. 通过PDO扩展连接MySQL数据库 2. 通过mysql扩展连接 3. php查询数据库出现中文乱码 3. 参 ...

  4. vue中遇到的问题:Error: Cannot find module 'chalk'

    安装 npm install chalk 如果还缺其他很多模块,那就 npm install 暴力解决问题

  5. nvidia-smi 实时查看

    需要用到 watch 命令: watch -n nvidia-smi

  6. Python_lambda

    最近学习到python的lambda表达式也是匿名函数, lambda不需要使用def 语句这样标准的形式定义一个函数,并不需要花很多时间去额外定义一个不常用的函数.lambda的本省就是一个长度为一 ...

  7. Idea导包与打包

    今天做了一个javavuser协议的性能测试,需要导入jar包,将jar包粘贴到lib下面后不知道怎么加到工程当中, 1,下面分享一下有关导包的流程: 先是在jar 右键,如图 : 选择项目结构,选择 ...

  8. Flask-Migrate

    终于到了Flask-Migrate,之前在看Flask-SQLAlchemy的时候, Flask支持 makemigration / migrate 吗? 答案在这里该诉你,如果你同时拥有两个三方组件 ...

  9. Tensorflow object detection API 搭建属于自己的物体识别模型

    一.下载Tensorflow object detection API工程源码 网址:https://github.com/tensorflow/models,可通过Git下载,打开Git Bash, ...

  10. CCF CSP 201409-1 相邻数对

    题目链接:http://118.190.20.162/view.page?gpid=T16 问题描述 试题编号: 201409-1 试题名称: 相邻数对 时间限制: 1.0s 内存限制: 256.0M ...