作用

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

检查

在 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. C++ 模拟Map

    JDK中的Map类型采用键值对的方式保存数据,且键(key)不能重复.在HashMap的实现中实际采用了Hash分类加数组排序的方式.在C++中我没有采用这样的算法.而是通过首先对Key值进行二叉树排 ...

  2. Webview组件和HTML的介绍

    Deviceone平台并不是基于html5的跨平台开发工具.我们开发一个app都是使用原生的组件,但是在某些场景下html5也是非常好的选择,比如复杂的图文混排(类似新闻),比如报表chart之类用h ...

  3. 教你如何查看一款App里面所包含的图片

    在开发制作App的过程中,有时候会想看看一些精美的App里面所设计的素材.这个时候就需要用到我给大家展现的方法了.下面就看看该如何操作能让一个App呈现出它原始的一面,这次我以Any.Do为例给大家演 ...

  4. python的tab自动补全

    vi tab.py #!/usr/bin/env python # python startup file import sys import readline import rlcompleter ...

  5. android 命令行

    android create avd --target --name cupcake 建立模拟器:           $ android create avd --target 2 --name c ...

  6. SQL锁死解决办法

    SQL Server 表,记录 死锁解决办法 1. 先根据以下语句 查询 哪些表被 死锁,及 死锁的 spid SELECT request_session_id spid,OBJECT_NAME(r ...

  7. win7和u盘redhat7.1双系统安装总结

    最近win7系统越用越卡,又没钱买mac只能想办法装以下linux系统,听说redhat服务器用的比较多,就想尝试一下装一个redhat.当然,和所有人一样,搜索了很多资料.我选择装双系统,因为要抛弃 ...

  8. Oracle客户端配置

    1.  打开开发生产数据库系统,点击下载Oracle_12C_Client32,并且解压缩. 2.  找到文件下的setup.exe文件,并且执行. 3.  等待数秒,在如下界面中选择第二项,管理员, ...

  9. C 语言

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

  10. ASP.NET MVC Jquery Validate 表单验证的多种方式

    在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体验也会得到很大的提升.在开发过程中我们可以不借助 JS 库,自己去手写 JS ...