当前位置: 首页 > news >正文

IDisposable接口和析构函数

IDisposable接口和析构函数

其实这是一个老话题了,只是刚才做程序的时候突然发现自己有些概念有点模糊,所以做了一个测试如下:

这段代码是MSDN中的例子修改而来。

None.gif using  System;
None.gif
using  System.ComponentModel;
None.gif
None.gif
//  The following example demonstrates how to create
None.gif
//  a resource class that implements the IDisposable interface
None.gif
//  and the IDisposable.Dispose method.
None.gif

None.gif
public   class  DisposeExample
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif    
public class MyDisposableMember: IDisposable
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private bool disposed = false;
InBlock.gif        
private string info;
InBlock.gif
InBlock.gif        
public MyDisposableMember(string _info)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            info 
= _info;
InBlock.gif            System.Diagnostics.Debug.WriteLine(
"\tMyDisposableMember:" + info);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            System.Diagnostics.Debug.WriteLine(
"\tDispose:" + info);
InBlock.gif            Dispose(
true);
InBlock.gif            GC.SuppressFinalize(
this);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private void Dispose(bool disposing)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(!this.disposed)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if(disposing)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
ExpandedSubBlockEnd.gif                }

InBlock.gif             
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            disposed 
= true;         
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
~MyDisposableMember()      
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            System.Diagnostics.Debug.WriteLine(
"\t~MyDisposableMember():" + info);
InBlock.gif            Dispose(
false);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif    
// A base class that implements IDisposable.
InBlock.gif    
// By implementing IDisposable, you are announcing that 
InBlock.gif    
// instances of this type allocate scarce resources.
InBlock.gif
    public class MyResource: IDisposable
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
// Track whether Dispose has been called.
InBlock.gif
        private bool disposed = false;
InBlock.gif        
private string info;
InBlock.gif        MyDisposableMember member;
InBlock.gif
InBlock.gif        
// The class constructor.
InBlock.gif
        public MyResource(string _info)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            info 
= _info;
InBlock.gif            System.Diagnostics.Debug.WriteLine(
"MyResource:" + info);
InBlock.gif            member 
= new MyDisposableMember("member-" + _info);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
// Implement IDisposable.
InBlock.gif        
// Do not make this method virtual.
InBlock.gif        
// A derived class should not be able to override this method.
InBlock.gif
        public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            System.Diagnostics.Debug.WriteLine(
"Dispose:" + info);
InBlock.gif            Dispose(
true);
InBlock.gif            
// This object will be cleaned up by the Dispose method.
InBlock.gif            
// Therefore, you should call GC.SupressFinalize to
InBlock.gif            
// take this object off the finalization queue 
InBlock.gif            
// and prevent finalization code for this object
InBlock.gif            
// from executing a second time.
InBlock.gif
            GC.SuppressFinalize(this);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
// Dispose(bool disposing) executes in two distinct scenarios.
InBlock.gif        
// If disposing equals true, the method has been called directly
InBlock.gif        
// or indirectly by a user's code. Managed and unmanaged resources
InBlock.gif        
// can be disposed.
InBlock.gif        
// If disposing equals false, the method has been called by the 
InBlock.gif        
// runtime from inside the finalizer and you should not reference 
InBlock.gif        
// other objects. Only unmanaged resources can be disposed.
InBlock.gif
        private void Dispose(bool disposing)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(!this.disposed)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// If disposing equals true, dispose all managed 
InBlock.gif                
// and unmanaged resources.
InBlock.gif
                if(disposing)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
// Dispose managed resources.
InBlock.gif
                    member.Dispose();
ExpandedSubBlockEnd.gif                }

InBlock.gif             
InBlock.gif                
// Call the appropriate methods to clean up 
InBlock.gif                
// unmanaged resources here.
InBlock.gif                
// If disposing is false, 
InBlock.gif                
// only the following code is executed.
InBlock.gif

InBlock.gif                member 
= null;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            disposed 
= true;         
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
// Use C# destructor syntax for finalization code.
InBlock.gif        
// This destructor will run only if the Dispose method 
InBlock.gif        
// does not get called.
InBlock.gif        
// It gives your base class the opportunity to finalize.
InBlock.gif        
// Do not provide destructors in types derived from this class.
InBlock.gif
        ~MyResource()      
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// Do not re-create Dispose clean-up code here.
InBlock.gif            
// Calling Dispose(false) is optimal in terms of
InBlock.gif            
// readability and maintainability.
InBlock.gif
            System.Diagnostics.Debug.WriteLine("~MyResource():" + info);
InBlock.gif            Dispose(
false);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
public static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
// Insert code here to create
InBlock.gif        
// and use the MyResource object.  
InBlock.gif
        MyResource mr = new MyResource("mr");
InBlock.gif        mr.Dispose();
InBlock.gif
InBlock.gif        
new MyResource("hang");
InBlock.gif
InBlock.gif        
using(MyResource m = new MyResource("using"))
InBlock.gif            System.Diagnostics.Debug.WriteLine(
"ready to exit using statement");
InBlock.gif
InBlock.gif        System.GC.SuppressFinalize(mr);
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//*
InBlock.gif    运行结果如下:
InBlock.gif    
InBlock.gifMyResource:mr
InBlock.gif    MyDisposableMember:member-mr
InBlock.gifDispose:mr
InBlock.gif    Dispose:member-mr
InBlock.gifMyResource:hang
InBlock.gif    MyDisposableMember:member-hang
InBlock.gifMyResource:using
InBlock.gif    MyDisposableMember:member-using
InBlock.gifready to exit using statement
InBlock.gifDispose:using
InBlock.gif    Dispose:member-using
InBlock.gif    ~MyDisposableMember():member-hang
InBlock.gif~MyResource():hang
InBlock.gif
ExpandedSubBlockEnd.gif     
*/

ExpandedBlockEnd.gif}

None.gif


从运行结果我们可以分析出如下的结果:

1。如果调用Dispose进行释放,则系统不会调用其析构函数
2。如果是系统自动释放的,则不会调用其Dispose函数,也就是说,.net垃圾收集器其实不认识 IDisposable接口。
3。在类析构过程中,会先释放其中的成员,最后再调用类的析构函数本身。

这里第3点需要说明一下,这是和C++中区别很大的地方,在C++中所有的释放都需要类的析构函数来进行,也就是在C++的析构函数中,所有的成员都是可用而且有效的。但是在C#中就会有区别了,因为C#的类析构函数调用之前,系统就会进行托管成员对象的清理工作。从生命周期的观点来看,类成员的生命周期必须包含在类的生命周期之内,C#这么做没有问题,但是问题时在于程序经常需要在析构函数中使用类的成员,所以就出现了异常情况:在析构函数中使用的类成员已经被析构了!也就是说,同样在析构函数范围内,C++包含的寓意是“析构=无效”,但是在C#的析构函数范围中,“析构 != 无效”。

由此,我们明白了为什么一些代码检查的软件会建议我们实现IDisposable时候,象例子中那样要自定义一个Dispose(bool disposing)了。

相关文章:

  • Codeforces Round #384 (Div. 2) E
  • 烂泥:python2.7和python3.5源码安装
  • 小改动
  • 部署web
  • 五一长假日记(1)
  • 【我拼搏的2016】-Python进行时
  • 关于建立控件、组件开发团队,有兴趣的网友请留言
  • mac安装tensorflow报错
  • 写跨浏览器脚本需要注意的问题
  • MySQL在Ubuntu系统的三种自启动方法
  • .net 程序发生了一个不可捕获的异常
  • SpringMVC学习笔记(一)
  • C#操作Excel,套用模板并对数据进行分页
  • 【SC】SCOM配置AD集成
  • 去了一趟微软
  • [deviceone开发]-do_Webview的基本示例
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • js
  • magento 货币换算
  • windows下mongoDB的环境配置
  • yii2权限控制rbac之rule详细讲解
  • 读懂package.json -- 依赖管理
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 飞驰在Mesos的涡轮引擎上
  • 高性能JavaScript阅读简记(三)
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 树莓派 - 使用须知
  • 追踪解析 FutureTask 源码
  • PostgreSQL之连接数修改
  • ​2020 年大前端技术趋势解读
  • ​iOS实时查看App运行日志
  • ​queue --- 一个同步的队列类​
  • ​虚拟化系列介绍(十)
  • $jQuery 重写Alert样式方法
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (初研) Sentence-embedding fine-tune notebook
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (分布式缓存)Redis持久化
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (三)elasticsearch 源码之启动流程分析
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (学习日记)2024.01.19
  • (转)ABI是什么
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转)母版页和相对路径
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .Net Core与存储过程(一)