C#学习之Dispose

2023-11-03

什么是资源:

首先要提出“什么是资源”。在CLR出来之后,Windows系统资源开始分为“非托管资源”和“托管资源”。

         非托管资源是指:所有的Window内核对象(句柄)都是非托管资源 ,如对于Stream,数据库连接,GDI+的相关对象,还有Com对象等等,这些资源并不是受到CLR管理;

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

 

其次再来讲,资源的释放方式。

         非托管资源:需要显式释放的,也即需要你写代码释放;

         托管资源:并不需要显式释放,但是如果引用类型本身含有非托管资源,则需要进行现实释放;

     

显式释放的C#实现:

显式释放的C#实现,由C#语法支持的有:

         1:实现IDisposable接口的Dispose方法;

         2:析构方法(终结器);

         不由C#语法支持,但是约定支持的显式释放是:

         3:提供显示释放方法,比如常用的Close方法;

 

Dispose、Close和析构方法异同点:

首先,你无法调用析构方法。析构方法是由垃圾回收机制进行调用的 。换句话来说,就是你不知道析构方法被调用的时机。严格意义上来说,它只是作为资源释放的一个补救措施。

资源释放的一个正确的措施是为类型实现IDisposable接口的Dispose。当你需要释放类型的资源的时候,应该显示的调用Dipose方法。当然,这里还有一个C#的语法糖,就是使用using程序块,在离开using程序块的时候,CLR会自动调用类型所创建对象的Dipose方法。

既然可以通过Dispose方法的方式来进行资源的释放,为什么有些类型还需要提供一个Close方法。这里面的区别,或者说约定在于,如果你仔细观察这些类型:他们基本都只公开了Close方法,他们都实现了IDisposable,但都隐藏了Dispose方法 。以Socket 这个类为例,它:

1:提供public void Close()

2:提供显式void IDisposable.Dispose()

3:提供protected virtual void Dispose(bool disposing)。真正的资源释放的代码放在这里。

 

理论上讲,提供Close方法最终还是使用的Dispose方法,之所以这么做,是因为这些类型出于显式实现IDisposable的因素, 在调用这些Dispose方法的时候,必须完成一次转型,如: 

           ((IDisposable)new A()).Dispose(); 

为了避免转型,同时也为了避免不熟悉C#语法的开发人员更直观的释放资源,提供了Close方法。

在上文的例子中,你可能已经注意到IDisposable.Dispose这个方法中,包含一句: 

      GC.SuppressFinalize(this); 

这是告诉CLR,在进行垃圾回收的时候,不用再继续调用析构方法(终结器)了。 是的,因为你已经手动释放资源了。这也从另一个方面验证了析构方法只是作为资源释放的补救机制。因为假设你忘记Close或者Dispose了,CLR会在垃圾回收的时候为你做这件事。查看Socket的析构函数,你会很好的理解这一点。

是的,析构方法调用的也是Dispose。

 

本文带来几个争论:

1:托管资源本身是否需要显式释放。答案显然是:不需要;

2:如果引用类型对象不再需要,是否需要显式=null;答案是:即使不这样做,GC也会进行垃圾回收。

3:将托管资源分为引用类型资源和值类型资源这种分类方法是有问题的,或者说是错误的。正确的分类法应该是栈资源和堆资源。线程栈中存放的是方法的 实参和方法内部的局部变量。堆上存放的是类型对象本身及对象的两个额外成员:类型对象指针和同步块索引。

4:Dispose方法本身是用来让你放置资源清理代码的。显然,一个空方法并不代表清理工作本身,真正执行清理工作的是你具体的代码。

 

推荐Dipose模式实现:

如:基类

子类:

 

Dispose实现的注意事项:

 

IDisposable.Dispose   方法
执行与释放或重置非托管资源相关的应用程序定义的任务。
使用此方法关闭或释放由实现此接口的类的实例保持的文件、流和句柄等非托管资源。根据约定,此方法用于与释放对象保持的资源或准备对象以便重新使用有关的 所有任务。

实现此方法时,可通过在包容层次结构中传播调用来确保释放所有保持的资源。例如,如果对象   A   分配对象   B,而对象   B   又分配对象   C,那么   A   的   Dispose   实现必须对   B   调用   Dispose,而   B   反过来必须对   C   调用   Dispose。如果一个对象的基类实现   IDisposable,该对象还必须调用其基类的   Dispose   方法。

如果某对象的   Dispose   方法被调用一次以上,则该对象必须忽略第一次调用后的所有调用。如果对象的   Dispose   方法被多次调用,该对象一定不要引发异常。除   Dispose   之外的实例方法在资源已释放时会引发   ObjectDisposedException。

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

C#学习之Dispose 的相关文章

  • 为什么 std::vector 可以处理类定义中的不完整类型?

    出现了以下问题 C 标准似乎说 std vector需要一个完整的类型才能工作 看https en cppreference com w cpp container vector https en cppreference com w cp
  • 错误:表达式不可赋值三元运算符

    我有以下代码 MPLABX XC8 编译器给出此错误 错误 表达式不可分配 U1ERRIRbits RXFOIF uart1 oerr 1 uart1 oerr 0 这是相关代码部分 typedef union struct bool fe
  • 无法在 CUDA 中找到 1 到 100 数字的简单和?

    我正在研究使用 CUDA 的图像处理算法 在我的算法中 我想使用 CUDA 内核找到图像所有像素的总和 所以我在cuda中制作了内核方法 来测量16位灰度图像的所有像素的总和 但我得到了错误的答案 所以我在cuda中编写了一个简单的程序来查
  • 如何使用T4从一个模板同时生成两个文件?

    我遇到的情况是 我需要生成两个 CSharp 代码文件 它们的代码几乎相同 但方法的输入和输出类型的命名空间不同 事实上 每个文件都针对特定国家 地区 并且类型来自特定国家 地区的 WSDL 我正在围绕服务编写一些包装器 逻辑完全相同 但从
  • CMake(Ninja 后端)使用 /MT 编译

    我有一个类似的问题CMake 使用 MT 而不是 MD 进行编译 https stackoverflow com questions 14172856 cmake compile with mt instead of md但有一些差异 我正
  • 如何以编程方式删除受信任的根证书颁发机构中的证书?

    我需要能够从组织中的每台电脑中删除特定的证书 是的 我可以逐个座位 但我要到周四才能完成 而且我没有人力逐个座位 是否有使用 C 的编程方式来执行此操作 我认为你不需要编写任何 C 看看certmgr exe del http msdn m
  • 维护 VS Test Project 中单元测试方法之间的上下文

    我想按顺序运行以下单元测试 使用随机数字的名称 密码等创建新客户 检索刚刚创建的客户并断言其属性包含相同的随机数 对同一用户调用 ForgotPassword 函数 并使用相同的随机数作为用户名 清楚地看到 我需要生成一次随机数 并在 3
  • 大量互斥体对性能的影响

    假设我有一个包含 1 000 000 个元素的数组 以及多个工作线程 每个线程都操作该数组中的数据 工作线程可能会使用新数据更新已填充的元素 但每个操作仅限于单个数组元素 并且独立于任何其他元素的值 使用单个互斥锁来保护整个数组显然会导致高
  • 重载算术运算符

    赋值运算符可以声明为 T 运算符 const t 在类中 但不能以这种方式定义算术运算符 它必须是友元函数 我不明白为什么 你能解释一下吗 算术运算符不必须是友元 那么你可以这样定义 MyClass MyClass operator con
  • 使用 STL 流时如何格式化我自己的对象?

    我想将我自己的对象输出到 STL 流 但具有自定义格式 我想出了这样的东西 但由于我之前从未使用过 locale 和 imbue 所以我不知道这是否有意义以及如何实现 MyFacet 和operator 所以我的问题是 这是否有意义以及如何
  • 如何在 C++ 中正确使用 cin.fail()

    我正在编写一个程序 从用户那里获取整数输入cin gt gt iUserSel 如果用户输入一个字母 程序就会进入无限循环 我试图用下面的代码来阻止这种情况 但程序进入无限循环并打印出 错误 输入 我该如何修复我的程序 cin gt gt
  • 更改私有模块片段是否会导致模块重新编译?

    On 此页面有关 C 20 模块功能 https www modernescpp com index php c 20 modules private module fragment and header units 我发现了这样的说法 借
  • C++网络序列化[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一种将 C 数据包序列化为网络流的解决方案 我在这里看到很多帖子提到人们 ACE 谷歌协议缓
  • Clang 5.0 上的 vsprintf 和 vsnprintf [-Wformat-nonliteral] 警告

    我有这段代码 static void err doit int errnoflag int level const char fmt va list ap int errno save unsigned long n char buf MA
  • 使用未命名命名空间而不是静态命名空间

    我可以假设在未命名命名空间中声明的对象相当于static namespace int x 1 static int x 2 FWIK 在这两种情况下 x将具有静态存储期限和内部链接 声明为的对象的所有规则也是如此static适用于未命名名称
  • Windows Phone 的 JSON 反序列化

    我正在尝试反序列化以下 JSON 但我真的不知道如何使用 JSON net 来完成这项工作 我正在使用 C 和 JSON Net 库 我的 JSON 如下 found 3 bounds 43 54919 172 62148 43 54487
  • c++ - <未解析的重载函数类型>

    在我的班级里叫Mat 我想要一个将另一个函数作为参数的函数 现在我有下面 4 个函数 但是在调用 print 时出现错误 第二行给了我一个错误 但我不明白为什么 因为第一行有效 唯一的区别是功能f不是班级成员Mat but f2是 失败的是
  • 在多线程环境中捕获信号

    我有一个大型程序 需要尽可能具有弹性 并且有大量线程 我需要捕获所有信号SIGBUS SIGSEGV 并在必要时重新初始化有问题的线程 或者禁用该线程以继续减少功能 我的第一个想法是做一个setjump 然后设置信号处理程序 可以记录问题
  • 使用空的weak_ptr作为参数调用map::count安全吗?

    打电话安全吗map count http www cplusplus com reference map map count on an 未初始化因此为空weak ptr http en cppreference com w cpp mem
  • NHibernate:无状态会话错误消息无法获取代理

    我正在使用 nHibernate 无状态会话来获取对象 更新一个属性并将对象保存回数据库 我不断收到错误消息 无状态会话无法获取代理 我在其他地方有类似的代码 所以我不明白为什么这不起作用 有谁知道问题可能是什么 我正在尝试更新Screen

随机推荐

  • 华为OD机试 - 跳房子II(Java)

    题目描述 跳房子 也叫跳飞机 是一种世界性的儿童游戏 游戏参与者需要分多个回合按顺序跳到第1格直到房子的最后一格 然后获得一次选房子的机会 直到所有房子被选完 房子最多的人获胜 跳房子的过程中 如果有踩线等违规行为 会结束当前回合 甚至可能
  • c++什么时候使用new,调用构造函数

    new 补充 构造函数的调用 对象 可以调用成员函数 不可以调用构造函数 我们无法像调用成员函数那样使用对象来调用构造函数 因为在构造函数构造出对象之前 对象是不存在的 因此构造函数被用来创建对象 而不能通过对象来调用 详见 构造函数的4种
  • 三台机器搭建redis集群过程及问题记录

    文章目录 1 前言 2 搭建集群 3 遇到的问题 4 相关文章 1 前言 Redis版本 5 0 4 服务器版本 Linux CentOS 6 CentOS 7 CentOS 9 redis集群需要至少要三个master节点 我们这里搭建三
  • prometheus 服务发现原理

    服务发现 概述 如上图 Prometheus核心功能包括服务发现 数据采集和数据存储 服务发现模块专门负责发现需要监控的目标采集点 target 信息 数据采集模块从服务发现模块订阅该信息 获取到target信息后 其中就包含协议 sche
  • selenium+python:Excel 存储数据,在已存在的Excel修改写入数据 并保存

    三 Excel文件的写入 思路 新建Excel表格 新增该表格的工作表 根据指定的行和列写入数据 保存Excel表格 参考链接 http www cnblogs com chjbbs p 4153239 html 具体代码如图 4 所示 4
  • MyBatis学习(四):MyBatis使用代理方法(接口)实现数据库的操作

    在第一篇简单的mybatis示例中 我们简单的介绍了如何通过SQL映射文件来实现对数据库的操作 在对数据库操作的时候是采用上图中的1 2来实现对数据库的操作 见上图就可以实现对数据库的操作了 但是这样做还是不太方便 有没有更好的方法呢 接口
  • 基于流计算 Oceanus(Flink) CDC 做好数据集成场景

    由于第一次做实时 所以踩坑比较多 见谅 测试环境用的flink 小公司没有用到hadoop组件 一 踩坑记录 1 本地代码的flink版本是flink1 15 4 生产环境是flink1 16 1 在使用侧输出流时报错 需要使用以下写法 需
  • Candy Machine--前缀和&&二分查找

    任意门 JB loves candy very much One day he finds a candy machine with N candies in it After reading the instructions of the
  • Web Components简单用法介绍

    目录 Web Components 使用方法 一 自定义元素 自定义元素的方法 1 自定义UserCard类 2 使用浏览器原生的 customElements define 方法 告诉浏览器 user card 元素与该类相连 3 在页面
  • 【C++】入门 --- 缺省参数&函数重载

    文章目录 一 缺省参数 1 基本概念 2 缺省参数的分类 全缺省参数 半缺省参数 缺省参数实用案例 二 函数重载 1 函数重载概念 1 参数类型不同 2 参数个数不同 3 参数类型顺序不同 三 C 支持函数重载的底层原理 函数名修饰 一 缺
  • 本地服务器与云服务器哪个好?

    本地服务器和云服务器是企业可以使用的两种不同的服务器设置 主要区别在于本地服务器托管 第三方提供商托管云服务器 那么 本地服务器和云服务器哪个更好呢 接下来 将带大家讨论本地服务器和云服务器的优缺点 并帮助您确定哪些设置适合我们的数据保护和
  • Vue中启动提示polyfill缺少-webpack v5版本导致

    安装 npm i node polyfill webpack plugin 因为我们的项目使用webpack v5 其中polyfill Node核心模块被删除 所以 我们安装它是为了在项目中访问这些模块 vue config js文件 c
  • 树莓派4b安装Ubuntu 18.04系统及图形桌面

    文章目录 1 准备工作 1 1 硬件 1 2 下载树莓派镜像 1 3 下载树莓派镜像工具 2 安装系统 2 1 SD卡格式化 2 2 安装系统 3 连接热点 4 启动树莓派 5 更改软件源 6 安装桌面 7 参考文献 8 树莓派开机后wif
  • 面向对象与面向过程

    文章目录 概述 半天的活动 将此思想用于指导开发编程 以下内容纯属个人理解 和胡说八道 如有雷同 绝对是抄袭 2023 05 01 22 14 概述 一种对理解面向对象毫无帮助的 对指导编程毫无意义的 绝对正确的废话是 面向对象就是万事万物
  • 计算机中数值的表示[原码,反码,补码]

    计算机里都是以补码的形式存储数据 电脑只能识别二进制的0和1 0 表示正 1表示负 一个数的最高位定义为符合号位 一个字节 8位 为例 原码 最高位符号位 0代表正数 1代表负数 非符号位为该数字绝对值的二进制 X 原 1 原 000000
  • CSRF漏洞的利用及修复

    文章目录 1 简介 2 攻击 2 1 GET型 2 1 1 寻找CSRF点 2 1 2 抓包 2 1 3 伪造 2 2 POST型 2 2 1 抓包 2 2 2 伪造 3 防范 1 简介 CSRF Cross Site Request Fo
  • HTTP简介,http是一个属于应用层的面向对象的协议

    引言 HTTP是一个属于应用层的面向对象的协议 由于其简捷 快速的方式 适用于分布式超媒体信息系统 它于1990年提出 经过几年的使用与发展 得到不断地完善和扩展 目前在WWW中使用的是HTTP 1 0的第六版 HTTP 1 1的规范化工作
  • 程序员的五种实用工具

    1 生成 RegEx RegexGPT 是编写 RegEx 模式的绝佳工具 它真的令人难以置信 试一试 你就知道了 它的工作原理是 给它一个示例文本 输入预期结果 你也可以稍微解释一下 这取决于你 然后选择要生成 RegEx 的语言 点击生
  • Vue3 PC端自适应

    安装依赖包 npm i lib flexible save npm install px2rem loader 引入 在main js中引入 import lib flexible flexible 修改flexible js文件 在项目下
  • C#学习之Dispose

    什么是资源 首先要提出 什么是资源 在CLR出来之后 Windows系统资源开始分为 非托管资源 和 托管资源 非托管资源是指 所有的Window内核对象 句柄 都是非托管资源 如对于Stream 数据库连接 GDI 的相关对象 还有Com