一、Close与Dispose这两种方法的区别
调用完了对象的Close方法后,此对象有可能被重新进行使用;而Dispose方法来说,此对象所占有的资源需要被标记为无用了,也就是此对象要被销毁,不能再被使用。例如常见.Net类库中的SqlConnection这个类,当调用完Close方法后,可以通过Open重新打开一个数据库连接,当彻底不用这个对象了就可以调用Dispose方法来标记此对象无用,等待GC回收。
二、三者的区别如图
析构函数 Dispose方法 Close方法 意义 销毁对象 销毁对象 关闭对象资源 调用方式 不能被显示调用,在GC回收是被调用 需要显示调用或者通过using语句 需要显示调用 调用时机 不确定 确定,在显示调用或者离开using程序块 确定,在显示调用时
三、析构函数 和 Dispose 的说明
Dispose需要实现IDisposable接口。
Dispose由开发人员代码调用,而析构函数由GC自动调用。
Dispose方法应释放所有托管和非托管资源。而析构函数只应释放非托管资源。因为析构函数由GC来判断调用,当GC判断某个对象不再需要的时候,则调用其析构方法,这时候该对象中可能还包含有其他有用的托管资源。
Dispose方法结尾处加上代码[GC.SuppressFinalize(this);],即告诉GC不需要再调用该对象的析构方法,否则,GC仍会在判断该对象不再有用后调用其析构方法,虽然程序不会出错,但影响系统性能。
析构函数 和 Dispose 释放的资源应该相同,这样即使类使用者在没有调用 Dispose 的情况下,资源也会在 Finalize 中得到释放。
Finalize 不应为 public。
通过系统GC频繁的调用析构方法来释放资源会降低系统性能,所以推荐显示调用Dispose方法。
有 Dispose 方法存在时,应该调用它,因为 Finalize 释放资源通常是很慢的。
四、Close函数的说明
Close 这个方法在不同的类中有不同的含义,并没有任何规定要求 Close 具有特殊的含义,也就是说 Close 并不一定要释放资源,您也可以让 Close 方法表示[关门]。 不过,由于 Close 有[关]的意思,通常也把 Close 拿来释放资源,这也是允许的。比如文件操作中,用 Close 释放对象似乎比 Dispose 含义更准确,于是在设计类时,可以将 Close 设为 public,将 Dispose 设为 protected,然后由 Close 调用 Dispose。 也就是说 Close 表示什么意思,它会不会释放资源,完全由类设计者决定。网上说[Close 调用 Dispose]这种方法是很片面的。在 SqlConnection 中 Close 只是表示关闭数据库连接,并没有释放 SqlConnection 这个对象资源。 根据经验,Close 和 Dispose 同时存在的情况下(均为 public),Close 并不表示释放资源,因为通常情况下,类设计者不应该使用两个 public 方法来释放相同的资源。
五、析构函数和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()方法。
dy("nrwz");
查看更多关于C#中析构函数、Dispose、Close方法的区别的详细内容...