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 ...
随机推荐
- 一次APP测试的感悟
项目经理担责任.产品担责任.测试只需要把测试中发现的问题展示出来.如实反应问题.谁担责任谁有权利决定上不上线.所以他们直接绕过了测试.APP的上线让我学到了很多东西,见识了很多东西,也感悟了很多.这是 ...
- 浮点型数据运算精度bug
/** * 校验是否为数字 * @param arg * @return */ function checkIsNumber(arg){ if(arg != null && arg.t ...
- Spring源代码解析
Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.itey ...
- 【GO】GO语言学习笔记三
7.数组: 几乎是最常用的数据类型了... 数组就是指一系列同一类型数据 的集合.数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数 组的长度. 常规的数组声明方法: ...
- 折半查找(java)(边学习边更新)
---恢复内容开始--- class ArrayTest3 { public static void main(String[] args) { //int [] arr=new int[]{54,4 ...
- Codeforces Round #342 (Div. 2)-B. War of the Corporations
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- 2017年1月3日 星期二 --出埃及记 Exodus 21:29
2017年1月3日 星期二 --出埃及记 Exodus 21:29 If, however, the bull has had the habit of goring and the owner ha ...
- mysql 实现 start with
自己写service----> 传入map(idsql,rssql,prior) idsql 查询id rssql 查询结果集 调用 以下方法 @param ids 要查询的起始 ...
- spring-listener&spring-task注解版本
1.spring-listener: a) import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextLi ...
- 【转】T-SQL查询进阶—理解SQL Server中的锁
简介 在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查 ...