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

2023-10-27

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模式的实现

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • boost::asio + std::future - 关闭套接字后访问冲突

    我正在编写一个简单的 TCP 客户端来发送和接收单行文本 异步操作由 std future 处理 以便于超时阻塞查询 不幸的是 我的测试应用程序在破坏服务器对象时因访问冲突而崩溃 这是我的代码 TCP客户端 hpp ifndef TCPCL
  • c和java语言中的换行符

    现在行分隔符取决于系统 但在 C 程序中我使用 n 作为行分隔符 无论我在 Windows 还是 Linux 中运行它都可以正常工作 为什么 在java中 我们必须使用 n 因为它与系统相关 那么为什么我们在c中使用 n 作为新行 而不管我
  • 如何使用MemoryCache代替Timer来触发一个方法?

    以下方法通过等待已运行操作的结果来处理并发请求 对数据的请求可能会使用相同 不同的凭据同时出现 对于每组唯一的凭据 最多可以有一个GetCurrentInternal呼叫正在进行中 当准备就绪时 该呼叫的结果将返回给所有排队的服务员 pri
  • 为 Visual Studio 2013 编译 Tesseract

    我正在尝试使用tesseract在 Visual Studio 2013 中 我在链接器 gt 输入 不是 libtesseract302 static lib 中使用 libtesseract302 lib 一切都正常 并且已编译并运行
  • 如何将 #ifdef DEBUG 添加到 Xcode?

    我的项目中有一些代码永远不应该在发布版本中使用 但在测试时很有用 我想做这样的事情 ifdef DEBUG Run my debugging only code endif 在 Xcode 4 中哪里添加 DEBUG 设置 我尝试将其放入
  • 读取文件特定行号的有效方法。 (奖励:Python 手册印刷错误)

    我有一个 100 GB 的文本文件 它是来自数据库的 BCP 转储 当我尝试导入它时BULK INSERT 我在第 219506324 行上收到一个神秘错误 在解决此问题之前 我想看看这一行 但可惜的是我最喜欢的方法 import line
  • 如何从 .resx 文件条目获取注释

    资源文件中的字符串有名称 值和注释 The ResXResourceReader类让我可以访问名称和值 有办法看评论吗 你应该能够得到Comment via ResXDataNode class http msdn microsoft co
  • C# Dns.GetHostEntry 不返回连接到 WiFi 的移动设备的名称

    我有一个 C 中的 Windows 窗体应用程序 我试图获取列表中所有客户端的主机名 下面给出的是 ra00l 来自此链接的代码示例 GetHostEntry 非常慢 https stackoverflow com questions 99
  • 使用 C 语言使用 strftime() 获取缩写时区

    我看过this https stackoverflow com questions 34408909 how to get abbreviated timezone and this https stackoverflow com ques
  • 无法在 Windows 运行时组件库的 UserControl 中创建依赖项属性

    我想在用户控件内创建数据可绑定属性 这个用户控件包含一个 Windows 运行时组件 项目 我使用下面的代码来创建属性 public MyItem CurrentItem get return MyItem GetValue Current
  • 获取 WPF 控件的所有附加事件处理程序

    我正在开发一个应用程序 在其中动态分配按钮的事件 现在的问题是 我希望获取按钮单击事件的所有事件 因为我希望删除以前的处理程序 我尝试将事件处理程序设置为 null 如下所示 Button Click null 但是我收到了一个无法分配 n
  • 单击 form2 上的按钮触发 form 1 中的方法

    我对 Windows 窗体很陌生 我想知道是否可以通过单击表单 2 中的按钮来触发表单 1 中的方法 我的表格 1 有一个组合框 我的 Form 2 有一个 保存 按钮 我想要实现的是 当用户单击表单 2 中的 保存 时 我需要检查表单 1
  • 未经许可更改内存值

    我有一个二维数组 当我第一次打印数组的数据时 日期打印正确 但其他时候 array last i 的数据从 i 0 到 last 1 显然是一个逻辑错误 但我不明白原因 因为我复制并粘贴了 for 语句 那么 C 更改数据吗 I use g
  • C++:.bmp 到文件中的字节数组

    是的 我已经解决了与此相关的其他问题 但我发现它们没有太大帮助 他们提供了一些帮助 但我仍然有点困惑 所以这是我需要做的 我们有一个 132x65 的屏幕 我有一个 132x65 的 bmp 我想遍历 bmp 并将其分成小的 1x8 列以获
  • Visual Studio 中的测试单独成功,但一组失败

    当我在 Visual Studio 中单独运行测试时 它们都顺利通过 然而 当我同时运行所有这些时 有些通过 有些失败 我尝试在每个测试方法之间暂停 1 秒 但没有成功 有任何想法吗 在此先感谢您的帮助 你们可能有一些共享数据 检查正在使用
  • 如何在 Blackberry Cascades 中显示具有特定号码的电话板

    我正在使用带有 C QT 和 QML 的 Blackberry Cascades 10 Beta 3 SDK 以及 Blackberry 10 Dev Alpha Simulator 和 QNX Momentics IDE 并且我正在尝试实
  • std::async 与重载函数

    可能的重复 std bind 重载解析 https stackoverflow com questions 4159487 stdbind overload resolution 考虑以下 C 示例 class A public int f
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • Process.Start() 方法在什么情况下返回 false?

    From MSDN https msdn microsoft com en us library e8zac0ca v vs 110 aspx 返回值 true 表示有新的进程资源 开始了 如果由 FileName 成员指定的进程资源 St
  • Linq-to-entities,在一个查询中获取结果+行数

    我已经看到了有关此事的多个问题 但它们已经有 2 年 或更长 的历史了 所以我想知道这方面是否有任何变化 基本思想是填充网格视图并创建自定义分页 所以 我还需要结果和行数 在 SQL 中 这将类似于 SELECT COUNT id Id N

随机推荐

  • React Hook 之 useMemo及 React.memo

    一 useMemo const memoizedValue useMemo gt computeExpensiveValue a b a b 返回一个 memoized 值 把 创建 函数和依赖项数组作为参数传入 useMemo 它仅会在某
  • 2021泰迪杯数据分析技能赛B题-肥料登记数据分析

    调用模块 import numpy as np import pandas as pd import matplotlib pyplot as plt import seaborn as sns plt rcParams font fami
  • iic通信原理_血氧饱和度传感器MAX30102模块的原理及编程

    一 简介 MAX30102是一个集成的脉搏血氧仪和心率监测仪生物传感器的模块 芯片 它集成了一个660nm红光LED 880nm红外光LED 光电检测器 光器件 以及带环境光抑制的低噪声电子电路 可通过软件关断模块 待机电流为零 实现电源始
  • OpenCV Mat类型及convertTo转换

    类型 在 Android OpenCv中给我们返回的 type 直接是 CV 8UC4 但是 在 C 中返回的是 16 等这些整型 所以 我找了个对照表 表头的 C1 C2 C3 C4 指的是通道 Channel 数 比如灰度图像只有 1
  • 获取当前访问的部分虚拟路径(Request.Url.GetLeftPart)

    Request Url GetLeftPart的应用 发送按钮
  • 2023牛寒2--Tokitsukaze and K-Sequence

    Tokitsukaze 有一个长度为 n 的序列 a 她想把这个序列划分成 k 个非空子序列 定义序列的值为这个序列中只出现一次的数字的个数 对于 k 1 n Tokitsukaze 想知道把序列 a 划分成 k 个非空子序列后 所有子序列
  • GCD->OC

    VHAsyncRun h VHAsyncRun h VHUpload Created by vhall on 2019 11 7 Copyright 2019 vhall All rights reserved typedef void V
  • 20230601

    20230703 mockito when 不生效 掘金 Java 单元测试 3 mock进阶 静态 final 私有方法mock 掘金 Mockito与PowerMock的使用基础教程 掘金 System out println Syst
  • Linux--数据链路层--ARP协议--0319-21

    目录 1 认识以太网 1 1 以太网帧格式 1 2 基于以太网帧简单模拟局域网通信 问题一 如果有多台主机都在发送数据呢 问题二 发送方知不知道自己的数据被影响了呢 1 3 MTU 1 3 1 MTU对IP协议的影响 1 3 2 MTU对U
  • C++之关联容器的erase使用

    对于关联容器 如map set multimap multiset 删除当前的iterator 仅仅会使当前的iterator失效 只要在erase时 递增当前的iterator即可 这是因为map之类的容器 使用了红黑树来实现 插入 删除
  • 软件工程提问回顾与个人总结

    项目 内容 作业所属课程 软件工程班级博客 作业要求请点击链接查看 作业要求 我在这个课程的目标 学习如何用工程化方法构建和维护软件 这个作业在哪个具体方面帮助我实现目标 通过回顾整个课程的学习 思考总结获得的收获 一 以前提问题的博客 提
  • Qt知识点梳理 —— 无边框图片背景窗体实现

    文章目录 实现效果 创建项目 项目源码 开发环境 实现效果 创建项目 首先创建项目 选择QMainWindow或者QWidget都可以 窗体中加入Layout 选择Vertical Layout或者Horizontal Layout都可以
  • Microsoft Office Word 2016关闭时无响应卡顿的解决方法

    1 在控制面板中找到Microsoft office 2 右键单击选择更改 3 尝试 Quick Rapair 4 等待修复 如果Quick Rapair修复完成还没有解决问题 选择Online repair 再尝试
  • Python入门第五天——[小甲鱼]零基础入门学习Python

    046 property方法的原理 property方法的原理 描述符 描述符就是将某种特殊类型的类的实例指派给另一个类的属性 MyDecriptor就是x的描述符 所以MyDecriptor类就是一个描述符类 通常带有get set和de
  • 关于Vue.config.devtools与Vue.config.productionTip

    1 关于Vue config devtools 1 类型 boolean 2 默认值 true 生产版为 false 3 用法 务必在加载 Vue 之后 立即同步设置以下内容 一般在main js中 Vue config devtools
  • IO之字符流

    1 字符输出流 public abstract class Writer extends Object implement Appendable Closeabel Flushable 写入字符流的抽象类 子类必须实现的方法仅有write
  • jittor框架

    sudo apt install python dev sudo pip install https github com Jittor jittor git python3 m jittor test test example http
  • 概率算法与代码

    一 随机数 随机数在概率算法设计中扮演着十分重要的角色 在现实计算机上无法产生真正的随机数 因此在概率算法中使用的随机数都是一定程度上随机的 即伪随机数 线性同余法是产生伪随机数的最常用的方法 由线性同余法产生的随机序列a0 a1 an满足
  • es实战-rebalance功能及源码解析

    rebalance tasks在es集群里面的表现形式 通过调用 GET cat tasks v API 返回结果中 action 为 internal index shard recovery start recovery 不仅仅是reb
  • C#中Dispose、析构函数、close的区别

    C 中Dispose 析构函数 close的区别 一 Close与Dispose这两种方法的区别 调用完了对象的Close方法后 此对象有可能被重新进行使用 而Dispose方法来说 此对象所占有的资源需要被标记为无用了 也就是此对象要被销