首先来看MSDN中关于这个接口的说明:
[ComVisible(true)] public interface IDisposable { // Methods void Dispose(); }
1.[ComVisible(true)]:指示该托管类型对 COM 是可见的.
2.此接口的主要用途是释放非托管资源。当不再使用托管对象时,垃圾回收器会自动释放分配给该对象的内存。但无法预测进行垃圾回收的时间。另外,垃圾回收器对窗口句柄或打开的文件和流等非托管资源一无所知。将此接口的Dispose方法与垃圾回收器一起使用来显式释放非托管资源。当不再需要对象时,对象的使用者可以调用此方法。
一:基本应用
1.我们来定义一个实现了IDisposable接口的类,代码如下:
public class CaryClass :IDisposable
{ public void DoSomething() { Console.WriteLine("Do some thing...."); } public void Dispose() { Console.WriteLine("及时释放资源"); } }
2.我们有两种方式来调用:
2.1.第一种方式,使用Using语句会自动调用Dispose方法,代码如下:
using (CaryClass caryClass = new CaryClass()) { caryClass.DoSomething(); }
2.2第二种方式,现实调用该接口的Dispose方法,代码如下:
CaryClass caryClass = new CaryClass(); try { caryClass.DoSomething(); } finally { IDisposable disposable = caryClass as IDisposable; if (disposable != null) disposable.Dispose(); }
两种方式的执行结果是一样的,如下图:
2.3.使用try/finally 块比使用 using 块的好处是即使using中的代码引发异常,CaryClass的Dispose方法仍有机
会清理该对象。所以从这里看还是使用try/catch好一些。
二:Disposable 模式
1.在.NET种由于当对象变为不可访问后将自动调用Finalize方法,所以我们手动调用IDisposable接口的Dispose方法
和对象终结器调用的方法极其类似,我们最好将他们放到一起来处理。我们首先想到的是重写Finalize方法,如下:
protected override void Finalize() { Console.WritleLine("析构函数执行..."); }
当我们编译这段代码的时候,我们发现编译器会报如下的错误:
这是因为编译器彻底屏蔽了父类的Finalize方法,编译器提示我们如果要重写Finalize方法我们要提供一个析构函数来
代替,下面我们就提供一个析构函数:
~CaryClass()
{
Console.WriteLine("析构函数执行...");
}
实际上这个析构函数编译器会将其转变为如下代码:
protected override void Finalize() { try { Console.WritleLine("析构函数执行..."); } finally { base.Finalize(); } }
2.然后我们就可以将Dispose方法的调用和对象的终结器放在一起来处理,如下:
public class CaryClass: IDisposable { ~CaryClass() { Dispose(); } public void Dispose() { // 清理资源
}
}
3.上面实现方式实际上调用了Dispose方法和Finalize方法,这样就有可能导致做重复的清理工作,所以就有了下面经典
Disposable 模式:
private bool IsDisposed=false; public void Dispose() { Dispose(true); GC.SupressFinalize(this); } protected void Dispose(bool Diposing) { if(!IsDisposed) { if(Disposing) { //清理托管资源
} //清理非托管资源 } IsDisposed=true; } ~CaryClass() { Dispose(false); }
3.1. SupressFinalize方法以防止垃圾回收器对不需要终止的对象调用 Object.Finalize()。
3.2. 使用IDisposable.Dispose 方法,用户可以在可将对象作为垃圾回收之前随时释放资源。如果调用了 IDisposable.Dispose 方法,此方法会释放对象的资源。这样,就没有必要进行终止。IDisposable.Dispose 应调用 GC.SuppressFinalize 以使垃圾回收器不调用对象的终结器。
3.3.我们不希望Dispose(bool Diposing)方法被外部调用,所以他的访问级别为protected 。如果Diposing为true则释放托管资源和非托管资源,如果 Diposing等于false则该方法已由运行库从终结器内部调用,并且只能释放非托管资源。
3.4.如果在对象被释放后调用其他方法,则可能会引发 ObjectDisposedException。
三:实例解析
1.下面代码对Dispose方法做了封装,说明如何在使用托管和本机资源的类中实现 Dispose(bool) 的常规示例:
public class BaseResource : IDisposable { // 非托管资源 private IntPtr handle; //托管资源 private Component Components; // Dispose是否被调用 private bool disposed = false; public BaseResource() { } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { // 释放托管资源 Components.Dispose(); } // 释放非托管资源,如果disposing为false, // 只有托管资源被释放 CloseHandle(handle); handle = IntPtr.Zero; // 注意这里不是线程安全的 } disposed = true; } // 析构函数只会在我们没有直接调用Dispose方法的时候调用 // 派生类中不用在次提供析构函数 ~BaseResource() { Dispose(false); } // 如果你已经调用了Dispose方法后在调用其他方法会抛出ObjectDisposedException public void DoSomething() { if (this.disposed) { throw new ObjectDisposedException(); } } } public class MyResourceWrapper : BaseResource { // 托管资源 private ManagedResource addedManaged; // 非托管资源 private NativeResource addedNative; private bool disposed = false; public MyResourceWrapper() { } protected override void Dispose(bool disposing) { if (!this.disposed) { try { if (disposing) { addedManaged.Dispose(); } CloseHandle(addedNative); this.disposed = true; } finally { base.Dispose(disposing); } } } }
2.使用CLR垃圾收集器,您不必再担心如何管理对托管堆分配的内存,不过您仍需清理其他类型的资源。托管类通过
IDisposable 接口使其使用方可以在垃圾收集器终结对象前释放可能很重要的资源。通过遵循 disposable 模式并且留
意需注意的问题,类可以确保其所有资源得以正确清理,并且在直接通过 Dispose 调用或通过终结器线程运行清理代码时
不会发生任何问题。
发表评论
-
平淡的2007
2007-12-24 08:04 783早上起来,送女朋友去公交车站,然后回来赶紧打开电脑,先 ... -
DreamSpark发布,高校学生免费使用Visual Studio 2008 Professional Edition 等微软软件
2008-02-20 13:23 1380今天上网无意中搜索到学生可以免费使用VS2008专业版,后来又 ... -
坚持学习WF(1):从HelloWorld开始
2008-04-04 16:30 849[置顶]坚持学习WF文章索 ... -
坚持学习WF(2):WF创作模式和设计时工具
2008-04-05 17:19 598[置顶]坚持学习WF文章索 ... -
坚持学习WF(3):WF框架概览
2008-04-08 07:27 735[置顶]坚持学习WF文章索 ... -
坚持学习WF(4):活动(Activity)和依赖属性(DependencyProperty)
2008-04-12 00:01 1101[置顶]坚持学习WF文章索引 活动(Activity) 活动 ... -
坚持学习WF(5):自定义活动(CustomActivity)
2008-04-13 15:25 881当WF提供的标准活动不能满足我们的需求的时候,我们就需要定义自 ... -
MOSS点滴(1):如何开发和部署feature
2008-04-16 21:35 806Features 是MOSS 2007以开箱即用的一套新功能, ... -
MOSS点滴(2):自定义Application Page
2008-04-19 20:07 809在MOSS中后台管理的页面都是Application Pag ... -
坚持学习WF(6):开发可复用的宿主程序
2008-04-21 21:45 659我们之前写工作流宿主 ... -
MOSS点滴(3):说说MOSS中的母版页
2008-04-25 21:15 1134MOSS中有两种页面:Site P ... -
MOSS点滴(4):实现Form认证
2008-04-29 21:12 666本文主要参考了网上的一些文章,但有些文章有些地方说的不是很明确 ... -
坚持学习WF(7):流程控制(Flow Control)
2008-04-30 18:10 771本文主要说说WF中和流 ... -
坚持学习WF(8):本地服务之调用外部方法
2008-05-09 08:17 718WF提供了一组核心服务 ... -
MOSS中的WebPart开发
2008-05-10 13:53 1024由于在asp.net1.1的时候asp.net中还没有webp ... -
坚持学习WF(9):本地服务之事件处理
2008-05-28 07:49 763[置顶]坚持学习WF文章索引 一:先来介绍两个活动 Even ... -
坚持学习WF(10):在工作流中使用关联
2008-06-01 13:03 657[置顶]坚持学习WF文章索 ... -
坚持学习WF(11):工作流通信与队列
2008-06-07 15:45 691[置顶]坚持学习WF文章索引 WF 提供的通信模型是构建于 ... -
MOSS中创建自定义内容类型
2008-06-12 20:23 1068一:简要介绍 某类内容 ... -
坚持学习WF(12):使用EventHandlingScopeActivity活动
2008-06-18 22:46 639[置顶]坚持学习WF文章索引 EventHandlingSco ...
相关推荐
4.5.1.2.IDisposable接口和destroy-method属性 4.5.2.让对象了解自己的容器 4.5.2.1.IObjectFactoryAware接口 4.5.2.2.IObjectNameAware接口 4.5.3.IFactoryObject接口 4.6.抽象与子对象定义 4.7.与IObjectFactory...
1.1.3 实现 IDisposable 接口... 4 1.2 String 操作... 5 1.2.1 使用 StringBuilder 做字符串连接... 5 1.2.2 避免不必要的调用 ToUpper 或 ToLower 方法... 5 1.2.3 最快的空串比较方法... 6 1.3 多线程... 6 ...
第20章 在用户控件和自定义控件中使用UpdatePanel 第21章 页面生命周期和异步的局部页面呈现 第22章 ASP.NET AJAX客户端PageRequestManager 第23章 异步局部页面呈现:服务器端处理 第24章 异步局部页面呈现:客户端...
ITransactionKeeper同时也实现了IDisposable接口,其Dispose方法能够在事务没有提交时进行事务回滚(如果已经提交,则什么也不做),利用这个机制和C#的using语法,可以很方便的编写一个在出现异常时回滚的事务操作...
此版本是opencvsharp4的完整C#源代码,...• 大部分继承了IDisposable接口,方便使用using语句 • 可以直接调用原始风格的OpenCV方法 • 可以将图像对象直接转换成GDI使用的Bitmap和WPF的WriteBitmap • 支持Mono等。
书中介绍了在设计框架时的最佳实践,提供了自顶向下的规范,其中所描述的规范普遍适用于规模不同、可重用程度不同的框架和软件。这些规范历经.NET框架三个版本的长期开发,凝聚了数千名开发人员的经验和智慧。微软的...
8.6 IDisposable 210 8.7 对象 210 8.7.1 Object.Equals 210 8.7.2 Object.GetHashCode 212 8.7.3 Object.ToString 213 8.8 Uri 214 8.9 System.Xml的使用 216 8.10 相等性操作符 218 8.10.1 值...
10.8 实现IDisposable接口和析构函数 198 10.9 不安全的代码 199 10.10 指针 200 10.11 使用指针优化性能 213 10.12 内容总结 217 11 泛型 218 11.1 泛型的概念 218 11.2 使用泛型 219 11.3 可空类型 219 ...
11.5.1 在C# 4.0中使用out类型参数修饰符允许协变性 331 11.5.2 在C# 4.0中使用in类型参数修饰符允许逆变性 332 11.5.3 数组对不安全协变性的支持 335 11.6 泛型的内部机制 335 11.6.1 基于值...