C# 中正确实现 IDisposable 接口
作用
此接口的主要用途是释放非托管资源。 当不再使用托管对象时,垃圾回收器会自动释放分配给该对象的内存。 但无法预测进行垃圾回收的时间。 另外,垃圾回收器对窗口句柄或打开的文件和流等非托管资源一无所知。
检查
在 Visual Studio 中运行代码分析的时候,如果某一个类中,包含了实现 IDisposable 模式的属性,则会提醒你该类同样需要实现 IDisposable 模式,而实现 IDisposable 模式是有一套固定的模式的。这种模式能更有效的防止内存泄漏,也能在某些地方更简洁的书写代码,比如 using 关键字就是专为此而生。
using 关键字
提供能确保正确使用 IDisposable 对象的方便语法。以下是示例:
using (Font font = new Font("Arial", 10.0f)) {byte charset = font.GdiCharSet;}
using 关键字保证在离开 using 作用域的时候一定会调用 font.Dispose 。所以,如果只是在局部使用了 IDisposable 变量,最好这样包起来,以防止内存泄漏。
实现 IDisposable
MSDN 提供了一套标准的实现模板,地址在这:CA1063: Implement IDisposable correctly,我稍微有一点修改的实现了自己的:
/// <summary>/// @author Easily/// </summary>public class BaseObject : IDisposable {private bool _enabled = true;public bool enabled {get { return _enabled; }}public void Dispose() {if (_enabled) {Dispose(true);}}private void Dispose(bool value) {if (_enabled) {_enabled = false;Destroy();if (value) {GC.SuppressFinalize(this);}}}virtual protected void Destroy() {// release managed resource here}~BaseObject() {Dispose(false);}}
需要释放的资源会在 Destroy 里面得到释放,所以,子类如果有需要释放的资源,必须重写 Destroy 。Destroy 只会被调用一次,之后 enabled 属性会被设置为 false,如果子类在运行过程中正在调用异步的方法,回调必须检查 enabled 属性。
并发版本实现
以上的实现在并发环境下很容易出问题,并发的情况下,需要对 _enabled 锁定,使用 lock 关键字即可:
lock (_lockObj) {_enabled = false;}
所以,这就需要所有用到 _enabled 的地方都进行锁定,还有一个方法,使用 Interlocked 提供的原子操作,以下是并发版本:
/// <summary>/// @author Easily/// </summary>public class BaseObject : IDisposable {private int _disposed;public void Dispose() {Dispose(true);GC.SuppressFinalize(this);}private void Dispose(bool disposing) {if (Interlocked.CompareExchange(ref _disposed, 1, 0) != 0) {return;}if (disposing) {Destroy();}}virtual protected void Destroy() {//}~BaseObject() {Dispose(false);}}
C# 中正确实现 IDisposable 接口的更多相关文章
- 如何正确实现 IDisposable 接口
MSDN建议按照下面的模式实现IDisposable接口: public class Foo: IDisposable { public void Dispose() { Dispose(true); ...
- 【C#学习笔记】 IDisposable 接口
在.net 编程环境中,系统的资源分为托管资源和非托管资源. 对于托管的资源的回收工作,是不需要人工干预回收的,而且你也无法干预他们的回收,所能够做的只是了解.net CLR如何做这些操作.也就是说对 ...
- .NET中IDisposable接口的基本使用
首先来看MSDN中关于这个接口的说明: [ComVisible(true)] public interface IDisposable { // Methods void Dispose(); } 1 ...
- 深入理解C#中的IDisposable接口
写在前面 在开始之前,我们需要明确什么是C#(或者说.NET)中的资源,打码的时候我们经常说释放资源,那么到底什么是资源,简单来讲,C#中的每一种类型都是一种资源,而资源又分为托管资源和非托管资源,那 ...
- C#中的IDisposable接口
深入理解C#中的IDisposable接口 写在前面 在开始之前,我们需要明确什么是C#(或者说.NET)中的资源,打码的时候我们经常说释放资源,那么到底什么是资源,简单来讲,C#中的每一种类型都是一 ...
- 深入理解C#中的IDisposable接口(转)
转自:https://www.cnblogs.com/wyt007/p/9304564.html 写在前面 在开始之前,我们需要明确什么是C#(或者说.NET)中的资源,打码的时候我们经常说释放资源, ...
- C#中对IDisposable接口的理解
http://blog.sina.com.cn/s/blog_8abeac5b01019u19.html C#中对IDisposable接口的理解 本人最近接触一个项目,在这个项目里面看到很多类实现了 ...
- 【转】C#中对IDisposable接口的理解
IDisposable接口定义:定义一种释放分配的资源的方法. .NET 平台在内存管理方面提供了GC(Garbage Collection),负责自动释放托管资源和内存回收的工作,但它无法对非托管资 ...
- IDisposable接口详解
转载:http://www.cnblogs.com/davyli/archive/2010/09/13/1825042.html 正确实现 IDisposable .NET中用于释放对象资源的接口是I ...
随机推荐
- JS 鼠标滚轮事件(mousewheel/DOMMouseScroll)
onmousewheel (FireFox不支持此事件) // IE/Opera/Chrome/Safari document.body.onmousewheel = function(event) ...
- C 一些基础
C语言的几个输入输出函数 #include <stdio.h> getchar(),putchar() scanf(),printf() 1->getchar()与scanf()唯一 ...
- Node包管理工具
Node包管理工具 只是简单的介绍一些工具的使用,有利于开发过程.除了介绍Node包管理工具,还介绍了前端打包工具,前端模块管理工具 Node包管理工具: --npm --cnpm ...
- php中include()和require()的区别
1.引用文件方式 对 include()来说,在include()执行时文件每次都要进行读取和评估:而对于require()来说,文件只处理一次(实际上,文件内容替换 了require()语句.这就意 ...
- Java RandomAccessFile用法
RandomAccessFile RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必相同:但是其大小和位置必须 ...
- 个人作业-Week2 案例分析
微软必应词典客户端的案例分析 第一部分 调研,评测 1)bug: 运行平台:iOS 10.0.2 必应词典版本:4.2.2 1. bug标题:词库加载错误 bug详细描述:学习界面中的经典词库出国考试 ...
- JS函数 计算 今日,昨日,本周,上周,本月
最近有个功能会进行数据的筛选于是便写了几个快速计算 今日,昨日,本周,上周,本月 范围的function 以便以后遇到同样的问题可以直接进行复用,代码如下: /* *获取今日的起始和结束时间 *返回值 ...
- 在C#中读取枚举值的描述属性
枚举: public enum EnumLanugage { [System.ComponentModel.Description("中文")] Chinese, English ...
- 使用扫描二维码打开app
应该不少人遇到过这种需求,扫描二维码打开app如果用户没有这个app则提示它跳转. 用网页直接来调用app是不打可能的,必须原生那边先做一些配置. 首先,安卓和苹果的调用方法是不同的. 所以我们需要先 ...
- CSS 如何使DIV层水平居中
今天用CSS碰到个很棘手的问题,DIV本身没有定义自己居中的属性, 网上很多的方法都是介绍用上级的text-align: center然后嵌套一层DIV来解决问题. 可是事实上这样的方法科学吗? 经过 ...