博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
正确实现 IDisposable 接口
阅读量:5101 次
发布时间:2019-06-13

本文共 2292 字,大约阅读时间需要 7 分钟。

 
前言: 之前在M$的一本工具书上看过该节内容,但慢慢地就忘记了, 在实际项目遇到类似的问题又要 google, 汗下, 于是写此篇blog作备忘录 。

虽然 .net 有垃圾回收机制(GC), 可自动进行大部分的资源清理工作,但开发人员仍旧应该养成良好的通过手动调用资源清理方法来进行资源回收的习惯, 让对象实现 IDisposable 接口正是 M$ 所推荐的, 该接口的原型为:
    // Summary:
    //     Defines a method to release allocated unmanaged resources.
    [ComVisible(true)]
    public interface IDisposable
    
{
        // Summary:
        //     Performs application-defined tasks associated with freeing, releasing, or
        //     resetting unmanaged resources.
        void Dispose();
    }
 注:.net 内部也有传说中的”析构函数“,就是 
Finalize(), 该函数由GC自动调用。
实现 Dispose 需要注意的是
1. 如果资源已手动释放过了,就应该通知GC,不要再对该对象执行 Finalize 操作
2. 确保重复执行 Dispose 时不会出错
根据以上规则, 简单的定义一个类 classSample
    public class classSample : IDisposable
    
{
        /// <summary>
        /// 该对象是否已被销毁过
        /// </summary>
        private bool disposed;
        /// <summary>
        /// 这就是传说中的 Finalize函数,是不是和C++的析构函数很像?
        /// </summary>
        ~classSample()
        {
            Console.WriteLine("对象被销毁");
            
            Dispose(false);
        }
        public void Dispose()
        {
            Console.WriteLine("手动销毁对象");
            Dispose(true);
            //通知GC, 偶已经被销毁过了,可以不用再管偶了。。。
            GC.SuppressFinalize(this);
        }
        /// <summary>
        /// Dispose
        /// </summary>
        /// <param name="disposing">是否由程序直接调用</param>
        protected void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    //该函数为手动调用,此处可进行托管资源的清理
                    //比如此类中有一个类型为 DataSet 的变量 dsData
                    //此处可调用该对象的 Dispose 方法来清理托管资源
                    dsData.Dispose();
                }
                //进行非托管资源的清理
                //非托管的资源主要为一些用 API 打开的文件句柄,设备场景句柄等
                //该类资源 GC 是无法管理的,只能依靠程序员自已释放
                //不同的资源, 释放方法不一样
                //例如:
                //释放文件句柄 (定义API的代码略。)
                CloseHandle(handle);
                //释放GDI 中的设备场景 (定义API的代码略。)
                ReleaseDC(hdc);
            }
            disposed = true;
        }
    }
注意 protected void Dispose(bool disposing) 函数, 清理托管资源和非托管资源的代码位置不要写反了,否则当一个托管对象已经被GC回收后,再去调用它的Dispose 方法, 系统会触发一个 ObjectDisposedException 异常
到这里 ,一个简单的实现 IDisposable 的类已经写好了, 再写段测试代码看看
        private void button1_Click(object sender, EventArgs e)
        
{
            classSample cls = new classSample();
        }
点击按钮, 再关闭程序, 可看到 output 窗口中显示 对象被销毁
 说明  Finalize 函数被执行了
换一个
        private void button1_Click(object sender, EventArgs e)
        
{
            classSample cls = new classSample();
            cls.Dispose();
        }
再看 output 窗口中,只显示了”手动销毁对象“, 说明在手动执行Dispose 后,已正确通知GC,不再执行Finalize函数。
小技巧: 可使用 using 关键字来定义对象的生存期,
超出 using范围 后,如果对象实现了IDisposable接口, 系统会自动调用其 Dispose 方法, 是不是很方便。
            using (classSample cls = new classSample())
            
{
            }
看,我并没有调用 Dispose 方法, output 窗口中还是会显示 ”手动销毁对象“.
 
https://www.cnblogs.com/michaelhuwei/archive/2007/12/28/1018646.html

转载于:https://www.cnblogs.com/cmblogs/p/9156322.html

你可能感兴趣的文章
医药箱APP静态小项目
查看>>
安装使用eclipse
查看>>
VC6.0调试技巧(一)(转)
查看>>
django 王中王8之踏青撒花
查看>>
linux命令
查看>>
类库与框架,强类型与弱类型的闲聊
查看>>
webView添加头视图
查看>>
字符环(openjudge 2755)
查看>>
php match_model的简单使用
查看>>
在NT中直接访问物理内存
查看>>
Intel HEX 文件格式
查看>>
SIP服务器性能测试工具SIPp使用指导(转)
查看>>
php_扑克类
查看>>
回调没用,加上iframe提交表单
查看>>
(安卓)一般安卓开始界面 Loding 跳转 实例 ---亲测!
查看>>
Mysql 索引优化 - 1
查看>>
LeetCode(3) || Median of Two Sorted Arrays
查看>>
JSDoc规范
查看>>
大话文本检测经典模型:EAST
查看>>
文本主题模型之LDA(一) LDA基础
查看>>