码农深耕 - 说说IDisposable
概要
C#提供了方便的垃圾回收机制,使我们几乎不再需要为资源管理费心。可事实上,能被垃圾回收释放掉的只是托管资源,非托管资源还是需要我们手动释放。而为了实现这一目的,C#提供了 IDisposable 接口,这篇文章就谈一谈 IDisposable 接口在使用中需要注意的地方。
实现
首先,IDisposable 接口非常简单,只包含一个方法 Dispose。在 IDisposable 接口的定义中可以看到明确的描述,它是用于释放非托管资源的 [1]。但是,想写出一个健壮的 IDisposable 实现却不是那么容易,好在微软为我们提供了一份详细的指南 [2][3],参照这份指南中的示例代码,我们就可以轻而易举的写出一份优秀的 IDisposable 接口实现代码了,这里不再进行详细说明。
那么那些资源是常见的非托管资源呢?根据我的经验,列举如下:
- 文件流
- 窗体句柄
- 图片
- 网络连接
- 数据库连接
在使用到上述资源时,不要忘记务必在使用之后调用它们的 Dispose 方法。为了保证资源释放,一般我们会利用 try / finally 块,在 finally 块中调用 Dispose 方法。针对这种需求,C# 为我们提供了 using 语法糖 [4],对于实现了 IDisposable 接口的对象,利用 using 语句,可以简单的完成资源释放。
需要注意的细节
注意事件退订
当我们调用了一个对象的 Dispose 方法之后,它的非托管资源就被释放掉了,但是这个对象仍然可以被访问。因此,如果在这个对象内订阅了其他对象的事件,务必在 Dispose 方法中将事件退订 [5]。否则,事件发布者再次触发事件时,这个已经释放掉资源的对象还是会响应该事件,如果在事件响应方法中尝试访问已经释放的资源,则会发生意料外的错误。
WinForm 控件
从父容器中移除控件
当我们从一个容器中将某个控件 Remove 掉,这个控件的句柄并不会被释放,如果我们忘记显示地调用该控件的 Dispose 方法,又频繁地创建、移除控件,很快就会因为句柄过多而发生异常,面对这种情况,往往一头雾水,很难找到发生异常的根本原因。在以往的工作中,我一般会选择将一个控件从容器中 Remove 之后,再调用该控件的 Dispose 方法。后来无意间发现直接调用控件的 Dispose 方法,它会自动将自己从父容器中移除,通过阅读源码 [6] 证实了这个特性,真的挺方便。
移除自己的子控件
上面提到调用一个控件的 Dispose 方法,会自动将自己从父容器中移除。那么 Dispose 方法会对自己的子控件产生什么影响呢?是否需要在调用 Dispose 之前,先遍历并释放所有子控件呢?答案是不用,控件会自动调用所有子控件的 Dispose 方法,通过源码 [7] 可以证实这一点。可见,控件的 Dispose 方法是没有副作用的,一旦调用,就可以带着自己的资源,消失在我们的系统中,这种实现的思路,值得我们借鉴学习。
结语
IDisposable 为我们提供了便利,弥补了自动垃圾回收的不足,掌握好这个接口,不仅可以使我们的开发水平更进一步,也可以让我们的产品稳定性更上层楼。
参考文献:
[1] IDisposable 接口 (https://docs.microsoft.com/en-us/dotnet/api/system.idisposable?view=netframework-4.7.2#definition)
[2] 清理非托管资源 (https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/unmanaged?view=netframework-4.7.2)
[3] Dispose 模式 (https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern)
[4] using 语法糖 (https://docs.microsoft.com/en-us/dotnet/api/system.idisposable?view=netframework-4.7.2#the-c-and-visual-basic-using-statement)
[5] 取消订阅 (https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-subscribe-to-and-unsubscribe-from-events#unsubscribing)
[6] 从父容器中移除 (https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,6013)
[7] 自动释放子控件的资源 (https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,6017)
码农深耕 - 说说IDisposable的更多相关文章
- 【整理】待毕业.Net码农就业求职储备
声明:本文题目来源于互联网,仅供即将从学校毕业的.Net码农(当然,我本人也是菜逼一个)学习之用.当然,学习了这些题目不一定会拿到offer,但是针对就业求职做些针对性的准备也是不错的.此外,除了技术 ...
- <开心一笑> 码农 黑客和2B程序员之间的区别
笔记本电脑 码农: 黑客: 2B程序员: 求2的32次方: 码农: System.out.println(Math.pow(2, 32)); 黑客: System.out.println(1L< ...
- 经典算法C++版(参考一线码农博文)
鉴于一线码农的算法博文基本通过C#完成,此处用C++再实现一遍,具体解法可参考其博文. 地址:http://www.cnblogs.com/huangxincheng/category/401959. ...
- [2013 eoe移动开发者大会]靳岩:从码农到极客的升级之路
(国内知名Android开发论坛 eoe开发者社区推荐:http://www.eoeandroid.com/) 前天,2013 eoe 移动开发者大会在国家会议中心召开,eoe 开发者社区创始人靳岩在 ...
- 专门为码农定制的14款创意的T裇(T-Shirt)设计
T裇衫是人们在各种场合都可穿着的服装,如在T裇衫上作适当的装饰,即可增添无穷的韵味.通过图案直接反映人类的精神风貌,你可以把日常生活中的兴趣.习惯.喜怒哀乐.嗜好等展露无疑,张扬个性.秀出自我.对于码 ...
- 老码农教你在 StackOverflow 上谈笑风生
作为一个高大上的码农,你肯定用到过 StackOverflow,必须的.会有人否定这个断言么?那他恐怕不是真正的码农,或者说还没入门.StackOverflow 对于码农的重要性,基本就和诸葛亮对刘备 ...
- 上不了Google是码农的悲哀
http://refyt.com/?r=34d1edb7dba42e8d 上不了Google是码农的悲哀.1. 资料大部分都在国外的网站,差不多倍感伤心.2. Google Play没有办法访问了.3 ...
- .net 码农转战 iOS - 初探
好久没写博客了,之前还打算把毕业设计中涉及到的两个算法拿出来说说(脸型分析 + 声音分析),博文都写了一半了,后来实在太忙了,那篇随笔也就沉在草稿列表中没动过. 我原先是专职 .net 开发的,在公司 ...
- IT码农哥放弃50万年薪:辞职卖咖喱凉皮(背后深藏功与名)_互联网的一些事
IT码农哥放弃50万年薪:辞职卖咖喱凉皮(背后深藏功与名)_互联网的一些事 IT码农哥放弃50万年薪:辞职卖咖喱凉皮(背后深藏功与名)
随机推荐
- 【LeetCode】162. Find Peak Element (3 solutions)
Find Peak Element A peak element is an element that is greater than its neighbors. Given an input ar ...
- [HNOI2002]营业额统计 Splay tree
Splay tree入门题,学好代码风格,学习HH大牛的,传送门.. #include <functional> #include <algorithm> #include & ...
- android开发新浪微博客户端 完整攻略 [新手必读]
开始接触学习android已经有3个礼拜了,一直都是对着android的sdk文档写Tutorials从Hello World到Notepad Tutorial算是初步入门了吧,刚好最近对微博感兴趣就 ...
- AutoFac文档4(转载)
目录 开始 Registering components 控制范围和生命周期 用模块结构化Autofac xml配置 与.net集成 深入理解Autofac 指导 关于 词汇表 自动装配 从容器中可用 ...
- 查看linux服务器硬盘IO读写负载
最近一台linux服务器出现异常,系统反映很慢,相应的应用程序也无法反映,而且还出现死机的情况,经过几天的观察了解,发现服务器压力很大,主要的压力来自硬盘的IO访问已经达到100% 为了方便各位和自己 ...
- unity, 由Matrix4x4提取Quaternion和Vector3 及 由Quaternion,Vector3构造Matrix4x4
一,由Matrix4x4提取Quaternion和Vector3 Quaternion getRotationFromMatrix(Matrix4x4 m) { return Quat ...
- CentOS-6.5下安装navicat for mysql
一.安装前准备 安装epel源 安装wine 如果不安装wine,则可能会出现安装完navicat for mysql后无法启动的情况. 二.安装epel源 cd /tmp ...
- C++和C#实现剪切板数据交互
c#端由于system.windows.form自带的剪切板功能太少,所以写了一个Helper类把接口转了出来.这样就可以用不同的uint的id了. 并且自带的剪切板必须执行在[STAThread]模 ...
- PHPStorm 10 激活
按照这篇东东的说法去做已经不行了~ 可以参考我的另外一篇~ 传送门: http://www.cnblogs.com/gssl/p/5686612.html 楼主的图片看不到,下面是我找到的.分享出来. ...
- JS中同步与异步的理解
你应该知道,javascript语言是一门“单线程”的语言,不像java语言,类继承Thread再来个thread.start就可以开辟一个线程,所以,javascript就像一条流水线,仅仅是一条流 ...