• Dispose CLose 析构函数 Finalize()


    析构函数不能显示调用,而对于Dispose、close方法来说,都需要进行显示调用才能被执行。
    一、Close与Dispose这两种方法的区别
    调用完了对象的Close方法后,此对象有可能被重新进行使用;而Dispose方法来说,此对象所占有的资源需要被标记为无用了,也就是此对象要被销毁,不能再被使用。例如常见.Net类库中的SqlConnection这个类,当调用完Close方法后,可以通过Open重新打开一个数据库连接,当彻底不用这个对象了就可以调用Dispose方法来标记此对象无用,等待GC回收。
    二、三者的区别如图
    析构函数 Dispose方法 Close方法
    意义 销毁对象 销毁对象 关闭对象资源
    调用方式 不能被显示调用,在GC回收是被调用 需要显示调用或者通过using语句 需要显示调用
    调用时机 不确定 确定,在显示调用或者离开using程序块 确定,在显示调用时
    三、析构函数 和 Dispose 的说明

    1. Dispose需要实现IDisposable接口。
    2. Dispose由开发人员代码调用,而析构函数由GC自动调用。
    3. Dispose方法应释放所有托管和非托管资源。而析构函数只应释放非托管资源。因为析构函数由GC来判断调用,当GC判断某个对象不再需要的时候,则调用其析构方法,这时候该对象中可能还包含有其他有用的托管资源。
    4. 通过系统GC频繁的调用析构方法来释放资源会降低系统性能,所以推荐显示调用Dispose方法。
    5. Dispose方法结尾处加上代码“GC.SuppressFinalize(this);”,即告诉GC不需要再调用该对象的析构方法,否则,GC仍会在判断该对象不再有用后调用其析构方法,虽然程序不会出错,但影响系统性能。
      6、析构函数 和 Dispose 释放的资源应该相同,这样即使类使用者在没有调用 Dispose 的情况下,资源也会在 Finalize 中得到释放。
      7、Finalize 不应为 public。
      8、有 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 方法来释放相同的资源。

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

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

  • 相关阅读:
    npm 彻底卸载
    Qt6.2LTS官方文档综述翻译学习
    [RTOS 学习记录] 工程管理工具make及makefile
    08.SCA-CNN
    大模型背景下软件工程的机遇与挑战
    什么是数据结构?什么是算法?怎么学习数据结构与算法?
    类和对象6:相关内置函数
    [leetcode 单调栈] 901. 股票价格跨度 M
    virtio-blk简易驱动
    【深度思考】聊聊JDK动态代理原理
  • 原文地址:https://blog.csdn.net/u013400314/article/details/126587235