作用

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

检查

在 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 里面得到释放,所以,子类如果有需要释放的资源,必须重写 Destroy 。Destroy 只会被调用一次,之后 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. Avg_row_length是怎么计算的?

    通过一下命令我们可以获取表的使用情况: root::>show table status like 'tbname'\G 结果: . row ************************** ...

  2. Vmware10如何打开vmware11建立的虚拟机

    先说一下办法: 使用文本工具打开VMware 虚拟机配置文件(*.vmx文件),找到"virtualHW.version"一行,将值11修改为10保存即可. 修改之前: 硬件兼容性 ...

  3. Linux 我的笔记

    /home/wangteng/workspace zsh  缩短路径名

  4. java Http编程小结

    1:什么是HTTP? 超文本传输协议(HyperText Transfer Protocol -- HTTP)是一个设计来使客户端和服务器顺利进行通讯的协议. HTTP在客户端和服务器之间以reque ...

  5. 深入分析ClassLoader

    首先介绍下ClassLoader: ClassLoader顾名思义就是类加载器,负责将Class加载到JVM中,事实上ClassLoader除了能将Class加载到JVM中之外,还有一个重要的作用就是 ...

  6. (10) 深入了解Java Class文件格式(九)

    转载:http://blog.csdn.net/zhangjg_blog/article/details/22432599 经过前八篇关于class文件的博客, 关于class文件格式的内容也基本上讲 ...

  7. Markdown使用指南(1)——基础语法

    [TOC] Markdown使用指南 标题 # 这是一级标题 ## 这是二级标题 ### 这是三级标题 ###### 这是六级标题 引用 > 这是一级引用 >> 这是二级引用 > ...

  8. C 语言

    1, //         char server[] = BaseNetServerIp; //        string  serverStr = _aliNetServerEnabled?Ne ...

  9. static变量引起的问题,List数据覆盖

    出现的问题:Listt加载数据时,后面加载的数据会覆盖前面的数据,把后面的数据变得和前面一样 原因:因为刚开始把添加的数据写成了静态变量,所以一个改了以后所有都改了 解决方法:把数据设成普通属性,非静 ...

  10. 解迷宫的C++的未完善编程代码........请大神们帮忙改善下.........

    这...................................................................... 我也是醉了 看不太懂,大神们求解............ ...