作用

此接口的主要用途是释放非托管资源。 当不再使用托管对象时,垃圾回收器会自动释放分配给该对象的内存。 但无法预测进行垃圾回收的时间。 另外,垃圾回收器对窗口句柄或打开的文件和流等非托管资源一无所知。

检查

在 Visual Studio 中运行代码分析的时候,如果某一个类中,包含了实现 IDisposable 模式的属性,则会提醒你该类同样需要实现 IDisposable 模式,而实现 IDisposable 模式是有一套固定的模式的。这种模式能更有效的防止内存泄漏,也能在某些地方更简洁的书写代码,比如 using 关键字就是专为此而生。

using 关键字

提供能确保正确使用 IDisposable 对象的方便语法。以下是示例:

  1. using (Font font = new Font("Arial", 10.0f)) {
  2. byte charset = font.GdiCharSet;
  3. }

using 关键字保证在离开 using 作用域的时候一定会调用 font.Dispose 。所以,如果只是在局部使用了 IDisposable 变量,最好这样包起来,以防止内存泄漏。

实现 IDisposable

MSDN 提供了一套标准的实现模板,地址在这:CA1063: Implement IDisposable correctly,我稍微有一点修改的实现了自己的:

  1. /// <summary>
  2. /// @author Easily
  3. /// </summary>
  4. public class BaseObject : IDisposable {
  5. private bool _enabled = true;
  6. public bool enabled {
  7. get { return _enabled; }
  8. }
  9. public void Dispose() {
  10. if (_enabled) {
  11. Dispose(true);
  12. }
  13. }
  14. private void Dispose(bool value) {
  15. if (_enabled) {
  16. _enabled = false;
  17. Destroy();
  18. if (value) {
  19. GC.SuppressFinalize(this);
  20. }
  21. }
  22. }
  23. virtual protected void Destroy() {
  24. // release managed resource here
  25. }
  26. ~BaseObject() {
  27. Dispose(false);
  28. }
  29. }

需要释放的资源会在 Destroy 里面得到释放,所以,子类如果有需要释放的资源,必须重写 DestroyDestroy 只会被调用一次,之后 enabled 属性会被设置为 false,如果子类在运行过程中正在调用异步的方法,回调必须检查 enabled 属性。

并发版本实现

以上的实现在并发环境下很容易出问题,并发的情况下,需要对 _enabled 锁定,使用 lock 关键字即可:

  1. lock (_lockObj) {
  2. _enabled = false;
  3. }

所以,这就需要所有用到 _enabled 的地方都进行锁定,还有一个方法,使用 Interlocked 提供的原子操作,以下是并发版本:

  1. /// <summary>
  2. /// @author Easily
  3. /// </summary>
  4. public class BaseObject : IDisposable {
  5. private int _disposed;
  6. public void Dispose() {
  7. Dispose(true);
  8. GC.SuppressFinalize(this);
  9. }
  10. private void Dispose(bool disposing) {
  11. if (Interlocked.CompareExchange(ref _disposed, 1, 0) != 0) {
  12. return;
  13. }
  14. if (disposing) {
  15. Destroy();
  16. }
  17. }
  18. virtual protected void Destroy() {
  19. //
  20. }
  21. ~BaseObject() {
  22. Dispose(false);
  23. }
  24. }

C# 中正确实现 IDisposable 接口的更多相关文章

  1. 如何正确实现 IDisposable 接口

    MSDN建议按照下面的模式实现IDisposable接口: public class Foo: IDisposable { public void Dispose() { Dispose(true); ...

  2. 【C#学习笔记】 IDisposable 接口

    在.net 编程环境中,系统的资源分为托管资源和非托管资源. 对于托管的资源的回收工作,是不需要人工干预回收的,而且你也无法干预他们的回收,所能够做的只是了解.net CLR如何做这些操作.也就是说对 ...

  3. .NET中IDisposable接口的基本使用

    首先来看MSDN中关于这个接口的说明: [ComVisible(true)] public interface IDisposable { // Methods void Dispose(); } 1 ...

  4. 深入理解C#中的IDisposable接口

    写在前面 在开始之前,我们需要明确什么是C#(或者说.NET)中的资源,打码的时候我们经常说释放资源,那么到底什么是资源,简单来讲,C#中的每一种类型都是一种资源,而资源又分为托管资源和非托管资源,那 ...

  5. C#中的IDisposable接口

    深入理解C#中的IDisposable接口 写在前面 在开始之前,我们需要明确什么是C#(或者说.NET)中的资源,打码的时候我们经常说释放资源,那么到底什么是资源,简单来讲,C#中的每一种类型都是一 ...

  6. 深入理解C#中的IDisposable接口(转)

    转自:https://www.cnblogs.com/wyt007/p/9304564.html 写在前面 在开始之前,我们需要明确什么是C#(或者说.NET)中的资源,打码的时候我们经常说释放资源, ...

  7. C#中对IDisposable接口的理解

    http://blog.sina.com.cn/s/blog_8abeac5b01019u19.html C#中对IDisposable接口的理解 本人最近接触一个项目,在这个项目里面看到很多类实现了 ...

  8. 【转】C#中对IDisposable接口的理解

    IDisposable接口定义:定义一种释放分配的资源的方法. .NET 平台在内存管理方面提供了GC(Garbage Collection),负责自动释放托管资源和内存回收的工作,但它无法对非托管资 ...

  9. IDisposable接口详解

    转载:http://www.cnblogs.com/davyli/archive/2010/09/13/1825042.html 正确实现 IDisposable .NET中用于释放对象资源的接口是I ...

随机推荐

  1. spring 笔记1: mvn 中Controller方法的参数不能是嵌套类(内部类)。

    最近做spring开发,个人认为,Controller和客户端js通讯时传递的参数类 只使用某几个方法,为了减少对其他功能的影响,想把参数类定义为Controller类的 嵌套类(内部类).但是实践发 ...

  2. HTML如何让文本两端对齐

    <p style="text-align:justify; text-justify:inter-ideograph;>日本驻华大使丹羽宇一郎:日中关系比夫妻还紧密日本驻华大使丹 ...

  3. Linux杂乱小知识点

    1.不同网段的主机不能建立TCP连接 2.TCP客户端可以用bind绑定自己的IP与port(一般情况下不需要绑定,port由系统自动分配) 3.accept() 函数返回一个套接字,send / r ...

  4. 双层路由设置,WAN口和LAN口连接的方法设置

    WAN口设置方法,社路由器分别为路1 和路2 1 路2的LAN口地址改为172.16.1.1,重启 2 笔记本改成172.16.1.X,然后进入设置,在里面WAN地址设置为静态地址 192.168.1 ...

  5. Cocosd-x的坐标系

    OpenGL 坐标系 :   原点在屏幕左下角,x 轴向右,y 轴向上. UI坐标体系       :   原点在屏幕左上角,x 轴向右,y 轴向下. 屏幕坐标系:    UI 世界坐标系:  也叫绝 ...

  6. Radmin Center 1.54 测试版

    软件简介:radmin center 用于集中管理安装了 radmin server 的服务器,支持一键远程管理,数据全部本地存储,关键数据使用RC4变形加密.同时保留了radmin的高安全性和高易用 ...

  7. mysql 批量导出建表语句 (视图,函数同理)

    import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream;import ja ...

  8. Android 跑马灯

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  9. Spring MVC中Action使用总结

    Spring MVC中每个控制器中可以定义多个请求处理方法即Action,Action可以有多个不同的参数,有多种类型的返回结果. 可以作为Action的参数类型有: 表单对象基本数据类型,包括包装类 ...

  10. 自己动手写Logistic回归算法

    假设一个数据集有n个样本,每个样本有m个特征,样本标签y为{0, 1}. 数据集可表示为: 其中,x(ij)为第i个样本的第j个特征值,y(i)为第i个样本的标签. X矩阵左侧的1相当于回归方程的常数 ...