博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
释放非托管资源 IDisposable模式的实现、使用
阅读量:5013 次
发布时间:2019-06-12

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

  与c++一样,c#可以定义析构函数。但c#的析构函数主要用于释放非托管资源。在Net中,由GC垃圾回收线程掌握对象资源的释放,程序员无法掌控析构函数的调用时机。为了完全掌控非托管资源的释放,Net提供一个IDisposable接口。

一、c#的析构函数

1.1 定义析构函数

class Program    {        static void Main(string[] args)        {        }        ~Program()//析构函数        { }    }

 1.2 编译器把析构函数解析成Finalize终结器方法

Finalize的具体实现

.method family hidebysig virtual instance void         Finalize() cil managed{  // Code size       14 (0xe)  .maxstack  1  .try  {    IL_0000:  nop    IL_0001:  nop    IL_0002:  leave.s    IL_000c  }  // end .try  finally  {    IL_0004:  ldarg.0    IL_0005:  call       instance void [mscorlib]System.Object::Finalize()    IL_000a:  nop    IL_000b:  endfinally  }  // end handler  IL_000c:  nop  IL_000d:  ret} // end of method Program::Finalize

 如同构造函数一样,析构函数会调用基类的析构函数。与构造函数相反的是,析构函数先完成自己的清理工作,再调用基类的析构函数。

二、IDisposable模式的实现

如何安全、快速的释放非托管资源?如果我们的类使用的非托管资源,如数据库连接、文件句柄,这些资源需做到:使用后立刻释放。如果我们只在析构函数实现释放,则无法达到使用后立刻释放这个目标。为了实现这个目标,Net引入了IDisposable模式。

 IDisposable的接口定义如下

public interface IDisposable    {        // Summary:        //     Performs application-defined tasks associated with freeing, releasing, or        //     resetting unmanaged resources.        void Dispose();    }

 我们来分析一下SqlConnection类的IDisposable模式的实现

SqlConnection继承于 , 继承于,里实现了

IDisposable接口,Component代码如下:

public class Component : MarshalByRefObject, IComponent, IDisposable{    // Methods    public void Dispose()    {        this.Dispose(true);释放托管资源        GC.SuppressFinalize(this);//请求系统不要调用指定对象的终结器. //该方法在对象头中设置一个位,系统在调用终结器时将检查这个位    }    protected virtual void Dispose(bool disposing)    {        if (disposing)        {            lock (this)            {                if ((this.site != null) && (this.site.Container != null))                {                    this.site.Container.Remove(this);                }                if (this.events != null)                {                    EventHandler handler = (EventHandler) this.events[EventDisposed];                    if (handler != null)                    {                        handler(this, EventArgs.Empty);                    }                }            }        }    }    ~Component()    {        this.Dispose(false);//有可能开发人员忘记调用Dispose方法,导致资源泄漏,为了避免这种情况,在析构函数调用Dispose,确保资源被释放    }   }

 在SqlConnection中重写了protected virtual void Dispose(bool disposing)方法,代码如下

protected override void Dispose(bool disposing)    {        if (disposing)        {            this._userConnectionOptions = null;//把本对象引用的其他对象设置成空            this._poolGroup = null;            this.Close();//关闭数据库连接        }        this.DisposeMe(disposing);        base.Dispose(disposing);//调用基类的Dispose    }

 三、正确调用Dispose方法

SqlConnection conn = new SqlConnection();            //do something;            conn.Dispose();

 这代码有漏洞,当do something出现异常时,导致Dispose执行不了,更安全的做法是:

class Program    {        static void Main(string[] args)        {            SqlConnection conn = new SqlConnection();            try            {                //do something;            }            finally            {                conn.Dispose();            }        }    }

 为了简化代码量,c#使用using简化输入,编译器自动翻译成 try...finally

class Program    {        static void Main(string[] args)        {            using(SqlConnection conn = new SqlConnection())            {                //do something;            }        }    }

 

转载于:https://www.cnblogs.com/50614090/archive/2012/04/11/2442274.html

你可能感兴趣的文章
Ubuntu最小化桌面快捷键Super+D不生效解决
查看>>
Cookie&Session会话跟踪技术
查看>>
UNIX环境高级编程 第17章 高级进程间通信
查看>>
ES的Zen发现机制
查看>>
【hibernate】1、Hibernate的一个注解 @Transient
查看>>
HihoCoder 1877 - Approximate Matching
查看>>
Elastic Search 语法总结
查看>>
py自动化之环境配置
查看>>
Winodws SNMP服务安装和配置(Windows 2003 & 2008 R2)
查看>>
红黑树-想说爱你不容易
查看>>
【题目】英文字符进行频率的统计,直方图输出
查看>>
LeetCode-Binary Tree Level Order Traversal
查看>>
COM组件开发实践
查看>>
yii2 源码分析1从入口开始
查看>>
浅谈网站推广
查看>>
Away3D基础之摄像机
查看>>
Leetcode 128. Longest Consecutive Sequence
查看>>
程序员必须知道的几个Git代码托管平台
查看>>
导电塑料入梦来
查看>>
C# 线程手册 第五章 扩展多线程应用程序 - 什么是线程池
查看>>