C# 中的析构函数实际上是重写了 System.Object 中的虚方法 Finalize 三种最常的方法如下: 1. 析构函数;(由GC调用,不确定什么时候会调用) 2. 继承IDisposable接口,实现Dispose方法;(可以手动调用。比如数据库的连接,SqlConnection.Dispose(),因为如 果及时释放会影响数据库性能。这时候会用到这个,再如:文件的打开,如果不释放会影响其它操作,如删除操作。调用Dispose后这个对象就不能再用了, 就等着被GC回收。) 3. 提供Close方法。(类似Dispose但是,当调用完Close方法后,可以通过Open重新打开) 析构函数不能显示调 用,而对于后两种方法来说,都需要进行显示调用才能被执行。而Close与Dispose这两种方法的区别在于,调用完了对 象的Close方法后,此对象有可能被重新进行使用;而Dispose方法来说,此对象所占有的资源需要被标记为无用了,也就是此对象要被销毁,不能再被 使用。例如常见.Net类 库中的SqlConnection这个类,当调用完Close方法后,可以通过Open重新打开一个数据库连接,当彻底不用这个对象了就可以调用 Dispose方法来标记此对象无用,等待GC回收。明白了这两种方法的意思后,大家在往自己的类中添加的接口时候,不要歪曲了这两者意思。 析构函数
Dispose方法
Close方法
意义
销毁对象
销毁对象
关闭对象资源
调用方式
不能被显示调用,在GC回收是被调用
需要显示调用或者 通过using语句
需要显示调用
调用时机
不确定
确定,在显示调用或者离开using程 序块
确定,在显示调用时
下面提供一个模式 来结合上面的 析构函数和Dispose方法。 public class BaseResource: IDisposable { //前面我们说了析 构函数实际上是重写了 System.Object 中的虚方法 Finalize, 默认情况下,一个类是没有析构函数的,也就是说,对象被垃圾回收时不会被调用Finalize方法 ~BaseResource() { // 为了保持代码的可读性性和可维护性,千万不要在这里写释放非托管资源的代码 // 必须以Dispose(false)方式调用,以false告诉Dispose(bool disposing)函数是从垃圾回收器在调用Finalize时调用的 Dispose(false); } // 无法被客户直接调用 // 如果 disposing 是 true, 那么这个方法是被客户直接调用的,那么托管的,和非托管的资源都可以释放 // 如果 disposing 是 false, 那么函数是从垃圾回收器在调用Finalize时调用的,此时不应当引用其他托管对象所以,只能释放非托管资源 protected virtual void Dispose(bool disposing) { // 那么这个方法是被客户直接调用的,那么托管的,和非托管的资源都可以释放 if(disposing) { // 释放 托管资源 OtherManagedObject.Dispose(); } //释放非托管资源 DoUnManagedObjectDispose(); // 那么这个方法是被客户直接调用的,告诉垃圾回收器从Finalization队列中清除自己,从而阻止垃圾回收器调用Finalize方法. if(disposing) GC.SuppressFinalize(this); } //可以被客户直接调用 public void Dispose() { //必须以Dispose(true)方式调用,以true告诉Dispose(bool disposing)函数是被客户直接调用的 Dispose(true); } } 上面的范例达到的目的: 1/ 如果客户没有调用Dispose(),未能及时释放托管和非托管资源,那么在垃圾回收时,还有机会执行Finalize(),释放非托管资源,但是造成了 非托管资源的未及时释放的空闲浪费 2/ 如果客户调用了Dispose(),就能及时释放了托管和非托管资源,那么该对象被垃圾回收时,不回执行Finalize(),提高了非托管资源的使用效 率并提升了系统性能 最后: 如果您的类中使用了非托管资源,则要考虑提供Close方法,和Open方法。并在您的Dispose方法中先调用 Close方法。 在使用已经 有类时,如SqlConnection。如果暂时不用这个连接,可以考虑用Close()方法。如果不用了就考虑调用 Dispose() 方法转载请注明来自: http://www.caodong.net/Article/825.html
Dispose方法
Close方法
意义
销毁对象
销毁对象
关闭对象资源
调用方式
不能被显示调用,在GC回收是被调用
需要显示调用或者 通过using语句
需要显示调用
调用时机
不确定
确定,在显示调用或者离开using程 序块
确定,在显示调用时
下面提供一个模式 来结合上面的 析构函数和Dispose方法。 public class BaseResource: IDisposable { //前面我们说了析 构函数实际上是重写了 System.Object 中的虚方法 Finalize, 默认情况下,一个类是没有析构函数的,也就是说,对象被垃圾回收时不会被调用Finalize方法 ~BaseResource() { // 为了保持代码的可读性性和可维护性,千万不要在这里写释放非托管资源的代码 // 必须以Dispose(false)方式调用,以false告诉Dispose(bool disposing)函数是从垃圾回收器在调用Finalize时调用的 Dispose(false); } // 无法被客户直接调用 // 如果 disposing 是 true, 那么这个方法是被客户直接调用的,那么托管的,和非托管的资源都可以释放 // 如果 disposing 是 false, 那么函数是从垃圾回收器在调用Finalize时调用的,此时不应当引用其他托管对象所以,只能释放非托管资源 protected virtual void Dispose(bool disposing) { // 那么这个方法是被客户直接调用的,那么托管的,和非托管的资源都可以释放 if(disposing) { // 释放 托管资源 OtherManagedObject.Dispose(); } //释放非托管资源 DoUnManagedObjectDispose(); // 那么这个方法是被客户直接调用的,告诉垃圾回收器从Finalization队列中清除自己,从而阻止垃圾回收器调用Finalize方法. if(disposing) GC.SuppressFinalize(this); } //可以被客户直接调用 public void Dispose() { //必须以Dispose(true)方式调用,以true告诉Dispose(bool disposing)函数是被客户直接调用的 Dispose(true); } } 上面的范例达到的目的: 1/ 如果客户没有调用Dispose(),未能及时释放托管和非托管资源,那么在垃圾回收时,还有机会执行Finalize(),释放非托管资源,但是造成了 非托管资源的未及时释放的空闲浪费 2/ 如果客户调用了Dispose(),就能及时释放了托管和非托管资源,那么该对象被垃圾回收时,不回执行Finalize(),提高了非托管资源的使用效 率并提升了系统性能 最后: 如果您的类中使用了非托管资源,则要考虑提供Close方法,和Open方法。并在您的Dispose方法中先调用 Close方法。 在使用已经 有类时,如SqlConnection。如果暂时不用这个连接,可以考虑用Close()方法。如果不用了就考虑调用 Dispose() 方法转载请注明来自: http://www.caodong.net/Article/825.html
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货