C#中Dispose、析构函数、close的区别

一、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方法实例

 1 public class BaseResource: IDisposable
 2 ...{
 3   ~BaseResource()
 4   ...{
 5   // 为了保持代码的可读性性和可维护性,千万不要在这里写释放非托管资源的代码
 6   // 必须以Dispose(false)方式调用,以false告诉Dispose(bool disposing)函数是从垃圾回收器在调用 析构函数 时调用的
 7      Dispose(false);
 8   }
 9   // 无法被客户直接调用
10   // 如果 disposing 是 true, 那么这个方法是被客户直接调用的,那么托管的,和非托管的资源都可以释放
11   // 如果 disposing 是 false, 那么函数是从垃圾回收器在调用Finalize时调用的,此时不应当引用其他托管对象所以,只能释放非托管资源
12   protected virtual void Dispose(bool disposing)
13   ...{
14   // 那么这个方法是被客户直接调用的,那么托管的,和非托管的资源都可以释放
15      if(disposing)
16      ...{
17   // 释放 托管资源
18         OtherManagedObject.Dispose();
19      }
20   //释放非托管资源
21      DoUnManagedObjectDispose();
22   // 那么这个方法是被客户直接调用的,告诉垃圾回收器从Finalization队列中清除自己,从而阻止垃圾回收器调用 析构函数 方法.
23      if(disposing)
24          GC.SuppressFinalize(this);
25   }
26   //可以被客户直接调用
27   public void Dispose()
28   ...{
29      //必须以Dispose(true)方式调用,以true告诉Dispose(bool disposing)函数是被客户直接调用的
30      Dispose(true);
31   }
32 }

参考:

托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象;

非托管资源:不受CLR管理的对象,windows内核对象,如文件、数据库连接、套接字、COM对象等;

改善C#程序的建议4:C#中标准Dispose模式的实现

时间: 2024-10-14 01:48:10

C#中Dispose、析构函数、close的区别的相关文章

C#中Dispose,finalize,GC,析构函数区别(转)

释放类所使用的未托管资源的两种方式:         1.利用运行库强制执行的析构函数,但析构函数的执行是不确定的,而且,由于垃圾收集器的工作方式,它会给运行库增加不可接受的系统开销.         2.IDisposable接口提供了一种机制,允许类的用户控制释放资源的时间,但需要确保执行Dispose(). 一般情况下,最好的方法是执行这两种机制,获得这两种机制的优点,克服其缺点.假定大多数程序员都能正确调用Dispose(),实现IDisposable接口,同时把析构函数作为一种安全的机

PHP中this,self,parent的区别

{一}PHP中this,self,parent的区别之一this篇 面向对象编程(OOP,Object OrientedProgramming)现已经成为编程人员的一项基本技能.利用OOP的思想进行PHP的高级编程,对于提高PHP编程能力和规划web开发构架都是很有意义的. PHP5经过重写后,对OOP的支持额有了很大的飞跃,成为了具备了大部分面向对象语言的特性的语言,比PHP4有了很多的面向对象的特性.这里我主要谈的是this,self,parent 三个关键字之间的区别.从字面上来理解,分别

C#中抽象类和接口的区别

原文:C#中抽象类和接口的区别 大家在编程时都容易把抽象类和接口搞混,下面为大家从概念上讲解抽象类和接口的区别: 一.抽象类: 含有abstract修饰符的class即为抽象类,抽象类是特殊的类,只是不能被实例化,可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例:除此以外,具有类的其他特性:重要的是抽象类可以包括抽象方法,这是普通类所不能的.抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们.另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖.

C#中抽象类和接口的区别与使用

一.抽象类: 抽象类是特殊的类,只是不能被实例化:除此以外,具有类的其他特性:重要的是抽象类可以包括抽象方法,这是普通类所不能的.抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们.另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们. 二.接口: 接口是引用类型的,类似于类,和抽象类的相似之处有三点: 1.不能实例化: 2.包含未实现的方法声明: 3.派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括

C#中结构与类的区别

一.类与结构的示例比较: 结构示例: 1 public struct Person 2 { 3 string Name; 4 int height; 5 int weight 6 public bool overWeight() 7 { 8 //implement something 9 } 10 } 类示例: 1 public class TestTime 2 { 3 int hours; 4 int minutes; 5 int seconds; 6 7 public void passti

转: PHP中this,self,parent的区别

{一}PHP中this,self,parent的区别之一this篇 面向对象编程(OOP,Object OrientedProgramming)现已经成为编程人员的一项基本技能.利用OOP的思想进行PHP的高级编程,对于提高PHP编程能力和规划web开发构架都是很有意义的. PHP5经过重写后,对OOP的支持额有了很大的飞跃,成为了具备了大部分面向对象语言的特性的语言,比PHP4有了很多的面向对象的特性.这里我主要谈的是this,self,parent 三个关键字之间的区别.从字面上来理解,分别

【翻译】JAVA中抽象类和接口的区别

不知道有没有人翻译过了,这篇是挺简单的,权当复习一遍内容吧. 很多常见的面试问题如"抽象类和接口有什么区别","你在什么时候用抽象类什么时候用接口".所以在这篇文章里面,我们会讨论一下这个话题. 在开始讨论它们的区别之前,我们先看看它们的介绍. Abstract class 抽象类 抽象类被用来抽象出子类的共同特征.它是不能被实例化的,它只能被子类继承作为超类使用.抽象类被用作它的子类下的层次结构创建模板(Abstract classes are used to c

lua中的pairs和ipairs区别

pairs Returns three values: the next function, the table t, and nil, so that the construction for k,v in pairs(t) do body end will iterate over all key–value pairs of table t. See function next for the caveats of modifying the table during its traver

浅谈HTTP中Get与Post的区别_转

可参考:HTTP请求中POST与GET的区别 Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作.到这里,大家应该有个大概的了解了,GET一般用于获取/查询资源信息,而POST一般用于更新资源信息. 1.根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的

python类中super()和__init__()的区别

本文和大家分享的主要是python开发中super()和__init__()的区别,希望通过本文的分享,对初学者学习这部分内容有所帮助. 1.单继承时super()和__init__()实现的功能是类似的 class Base(object): def __init__(self): print 'Base create' class childA(Base): def __init__(self): print 'creat A ', Base.__init__(self) class chi