C#学习笔记---Dispose(),Finalize(),SuppressFinalize
http://www.cnblogs.com/eddyshn/archive/2009/08/19/1549961.html
在.NET的对象中实际上有两个用于释放资源的函数:Dispose和Finalize。Finalize的目的是用于释放非托管的资源,而Dispose是用于释放所有资源,包括托管的和非托管的。
在这个模式中,void Dispose(bool disposing)函数通过一个disposing参数来区别当前是否是被Dispose()调用。如果是被Dispose()调用,那么需要同时释放托管和非托管的资源。如果是被~Foo()(也就是C#的Finalize())调用了,那么只需要释放非托管的资源即可。
这是因为,Dispose()函数是被其它代码显式调用并要求释放资源的,而Finalize是被GC调用的。在GC调用的时候Foo所引用的其它托管对象可能还不需要被销毁,并且即使要销毁,也会由GC来调用。因此在Finalize中只需要释放非托管资源即可。另外一方面,由于在Dispose()中已经释放了托管和非托管的资源,因此在对象被GC回收时再次调用Finalize是没有必要的,所以在Dispose()中调用GC.SuppressFinalize(this)避免重复调用Finalize。
然而,即使重复调用Finalize和Dispose也是不存在问题的,因为有变量m_disposed的存在,资源只会被释放一次,多余的调用会被忽略过去。
因此,上面的模式保证了:
1、 Finalize只释放非托管资源;
2、 Dispose释放托管和非托管资源;
3、 重复调用Finalize和Dispose是没有问题的;
4、 Finalize和Dispose共享相同的资源释放策略,因此他们之间也是没有冲突的。
在C#中,这个模式需要显式地实现,其中C#的~Foo()函数代表了Finalize()。而在C++/CLI中,这个模式是自动实现的,C++的类析构函数则是不一样的。
按照C++语义,析构函数在超出作用域,或者delete的时候被调用。在Managed C++(即.NET 1.1中的托管C++)中,析构函数相当于CLR中的Finalize()方法,在垃圾收集的时候由GC调用,因此,调用的时机是不明确的。在.NET 2.0的C++/CLI中,析构函数的语义被修改为等价与Dispose()方法,这就隐含了两件事情:
1、 所有的C++/CLI中的CLR类都实现了接口IDisposable,因此在C#中可以用using关键字来访问这个类的实例。
2、 析构函数不再等价于Finalize()了。
----------------------------别人总结------------------------
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方法能够被调用到,确保可以手动释放任何需要释放的资源。
C#学习笔记---Dispose(),Finalize(),SuppressFinalize的更多相关文章
- [学习笔记] Dispose模式
Dispose模式是.NET中很基础也很重要的一个模式,今天重新复习一下相关的东西并记录下来. 什么是Dispose模式? 什么时候我们该为一个类型实现Dispose模式 使用Dispose模式时应该 ...
- Thinking in java学习笔记之finalize
finalize:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下次垃圾回收动作发生时,才会真正回收对象占用的内存,所以可用此作为对象终结条件的验证.注意的三 ...
- .NET GC机制学习笔记
学习笔记内容来自网络资料摘录http://www.cnblogs.com/springyangwc/archive/2011/06/13/2080149.html 1.GC介绍 Garbage Col ...
- RAC学习笔记
RAC学习笔记 ReactiveCocoa(简称为RAC),是由Github开源的一个应用于iOS和OS开发的新框架,Cocoa是苹果整套框架的简称,因此很多苹果框架喜欢以Cocoa结尾. 在学习Re ...
- 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用
垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...
- 《Java学习笔记(第8版)》学习指导
<Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...
- Rest API 开发 学习笔记(转)
Rest API 开发 学习笔记 概述 REST 从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表示方式.获得这些表徵致使这些应用程序转变了其状态.随着 ...
- Dynamic CRM 2013学习笔记(三十一)自定义用excel批量导入实体数据
有一个实体的子表数据量太大,于是客户想用execel来导入实体数据.首先想到的是用系统自带的Import Data,客户嫌太麻烦,比如lookup字段要做map等. 下面是具体的实现步骤: 一.定义e ...
- C#学习笔记(六)——面向对象编程简介
一.面向对象编程的含义 * 是一种模块化编程方法,使代码的重用性大大的增加. * oop技术使得项目的设计阶段需要的精力大大的增加,但是一旦对某种类型的数据表达方式达成一致,这种表达方式就可以 ...
随机推荐
- BZOJ 3230: 相似子串
3230: 相似子串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1485 Solved: 361[Submit][Status][Discuss ...
- <<< Google hack
使用Google等搜索引擎对某些特定的网络主机漏洞(通常是服务器上的脚本漏洞)进行搜索,以达到快速找到漏洞主机或特定主机的漏洞的目的. 在SEO优化中,通常使用这种技术达到入侵一些网站挂外链之用.黑帽 ...
- RabbitMQ简介
AMQP简介 在了解RabbitMQ之前,首先要了解AMQP协议.AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消 ...
- HTML5新标签 w3c
w3c标准下的HTML5新标签 ,做个归纳总结: H5标签 定义和用法 兼容性 <artical> 规定独立的自包含内容, 支持html中的全局属性, 支持html中的事件属性 IE: 支 ...
- SDL 截图、录像、录像播放
截图 使用sdl很简单,视频显示窗口大小,不是视频分辨率大小 int i = Sdl.SDL_SaveBMP(surfacePtr, path); if(i != 0) { MessageBox.Sh ...
- [Unity3D]导入模型并且设置相应的属性
将资源拷贝到Assets中并设置 首先确保法线贴图的属性如下: 设置基本贴图和法线贴图 因为要发布到移动端,设置shader属性: 为了设置更好的反光效果,添加cubemap: 添加新的Materia ...
- 深入理解javascript原型和闭包(17)——补this
本文对<深入理解javascript原型和闭包(10)——this>一篇进行补充,原文链接:http://www.cnblogs.com/wangfupeng1988/p/3988422. ...
- [NHibernate]N+1 Select查询问题分析
目录 写在前面 文档与系列文章 N+1 Select查询问题分析 总结 写在前面 在前面的文章(延迟加载,立即加载)中都提到了N+1 Select的问题,总觉得理解的很不到位,也请大家原谅,这也是为什 ...
- PHP数组
PHP数组的遍历 使用for语句循环遍历数组 在PHP中,不仅可以指定非连续的数字索引值,而且还存在以字符串为下表的关联数组.所以在php中很少使用for语句循环来遍历数组.使用for语句遍历连续数字 ...
- Linux下百度云盘报 获取bdstoken失败
在用linux下百度云盘工具(bcloud),登录时,报获取bdstoken失败. 在网上搜了一下,解决办法如下. 找到auth.py文件 locate auth.py |grep bcloud 结果 ...