需要明确一下C#程序(或者说.NET)中的资源。简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类:

托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象;

非托管资源:不受CLR管理的对象,windows内核对象,如文件、数据库连接、套接字、COM对象等;

毫无例外地,如果我们的类型使用到了非托管资源,或者需要显式释放的托管资源,那么,就需要让类型继承接口IDisposable。这相当于是告诉调用者,该类型是需要显式释放资源的,你需要调用我的Dispose方法。

不过,这一切并不这么简单,一个标准的继承了IDisposable接口的类型应该像下面这样去实现。这种实现我们称之为Dispose模式:

publicclassSampleClass : IDisposable

{

//演示创建一个非托管资源privateIntPtr nativeResource =Marshal.AllocHGlobal(100);

//演示创建一个托管资源privateAnotherResource managedResource =newAnotherResource();

privatebooldisposed =false;

//实现IDisposable中的Dispose方法

///publicvoidDispose()

{

//必须为trueDispose(true);

//通知垃圾回收机制不再调用终结器(析构器)GC.SuppressFinalize(this);

}

//不是必要的,提供一个Close方法仅仅是为了更符合其他语言(如C++)的规范

///publicvoidClose()

{

Dispose();

}

//必须,以备程序员忘记了显式调用Dispose方法

///~SampleClass()

{

//必须为falseDispose(false);

}

//非密封类修饰用protected virtual

///密封类修饰用private

//protectedvirtualvoidDispose(booldisposing)

{

if(disposed)

{

return;

}

if(disposing)

{

//清理托管资源if(managedResource !=null)

{

managedResource.Dispose();

managedResource =null;

}

}

//清理非托管资源if(nativeResource !=IntPtr.Zero)

{

Marshal.FreeHGlobal(nativeResource);

nativeResource =IntPtr.Zero;

}

//让类型知道自己已经被释放disposed =true;

}

publicvoidSamplePublicMethod()

{

if(disposed)

{

thrownewObjectDisposedException("SampleClass", "SampleClass is disposed");

}

//省略}

}

在Dispose模式中,几乎每一行都有特殊的含义。

在标准的Dispose模式中,我们注意到一个以~开头的方法:

//必须,以备程序员忘记了显式调用Dispose方法

///~SampleClass()

{

//必须为falseDispose(false);

}

这个方法叫做类型的终结器。提供终结器的全部意义在于:我们不能奢望类型的调用者肯定会主动调用Dispose方法,基于终结器会被垃圾回收器调用这个特点,终结器被用做资源释放的补救措施。

一个类型的Dispose方法应该允许被多次调用而不抛异常。鉴于这个原因,类型内部维护了一个私有的布尔型变量disposed:

private bool disposed = false;

在实际处理代码清理的方法中,加入了如下的判断语句:

if(disposed)

{

return;

}

//省略清理部分的代码,并在方法的最后为disposed赋值为truedisposed =true;

这意味着类型如果被清理过一次,则清理工作将不再进行。

应该注意到:在标准的Dispose模式中,真正实现IDisposable接口的Dispose方法,并没有实际的清理工作,它实际调用的是下面这个带布尔参数的受保护的虚方法:

//非密封类修饰用protected virtual

///密封类修饰用private

//protectedvirtualvoidDispose(booldisposing)

{

//省略代码}

之所以提供这样一个受保护的虚方法,是为了考虑到这个类型会被其他类继承的情况。如果类型存在一个子类,子类也许会实现自己的Dispose模式。受保护 的虚方法用来提醒子类必须在实现自己的清理方法的时候注意到父类的清理工作,即子类需要在自己的释放方法中调用base.Dispose方法。

还有,我们应该已经注意到了真正撰写资源释放代码的那个虚方法是带有一个布尔参数的。之所以提供这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源。

在供调用者调用的显式释放资源的无参Dispose方法中,调用参数是true:

publicvoidDispose()

{

//必须为trueDispose(true);

//其他省略}

这表明,这个时候代码要同时处理托管资源和非托管资源。

在供垃圾回收器调用的隐式清理资源的终结器中,调用参数是false:

~SampleClass()

{

//必须为falseDispose(false);

}

这表明,隐式清理时,只要处理非托管资源就可以了。

那么,为什么要区别对待托管资源和非托管资源。在认真阐述这个问题之前,我们需要首先弄明白:托管资源需要手动清理吗? 不妨先将C#中的类型分为两类,一类继承了IDisposable接口,一类则没有继承。前者,我们暂时称之为非普通类型,后者我们称之为普通类型。非普 通类型因为包含非托管资源,所以它需要继承IDisposable接口,但是,这个包含非托管资源的类型本身,它是一个托管资源。所以说,托管资源需要手 动清理吗?这个问题的答案是:托管资源中的普通类型,不需要手动清理,而非普通类型,是需要手动清理的(即调用Dispose方法)。

Dispose模式设计的思路基于:如果调用者显式调用了Dispose方法,那么类型就该按部就班为自己的所以资源全部释放掉。如果调用者忘记调用 Dispose方法,那么类型就假定自己的所有托管资源(哪怕是那些上段中阐述的非普通类型)全部交给垃圾回收器去回收,而不进行手工清理。理解了这一 点,我们就理解了为什么Dispose方法中,虚方法传入的参数是true,而终结器中,虚方法传入的参数是false。

注意:我们提到了需要及时释放资源,却并没有进一步细说是否需要及时让引用等于null这一点。有一些人认为等于null可以帮助垃圾回收机制早点发现并标识对象是垃圾。其他人则认为这没有任何帮助。下一篇“

dispose 模式 java_C#中标准Dispose模式的实现相关推荐

  1. Java实现二十三种设计模式(五)—— 十一种行为型模式 (中)——解释器模式、迭代器模式、中介者模式、备忘录模式

    Java实现二十三种设计模式(五)-- 十一种行为型模式 (中)--解释器模式.迭代器模式.中介者模式.备忘录模式 一.解释器模式 我国 IT 界历来有一个汉语编程梦,虽然各方对于汉语编程争论不休,甚 ...

  2. 命令模式 java_JAVA中的命令模式实例教程

    原文链接  作者:Pankaj Kumar 译者:f0tlo <1357654289@qq.com> 命令模式是一种行为模式,因此,它处理的是对象的行为.命令模式为系统中不同的对象提供中性 ...

  3. java模板方法模式_Java中的模板方法模式

    java模板方法模式 模板方法模式是一种行为模式,建议在超类中更一般地定义算法. 该算法是在称为模板方法的方法中定义的. 子类仅定义更具体的算法步骤的实现. 使用这种设计模式的好处是,算法后面的任何更 ...

  4. swift 听筒模式_Swift中的“复合”模式

    swift 听筒模式 定义 (Definition) 'Composite' pattern is a structural design pattern that is useful for com ...

  5. 计算机的上帝模式,电脑中的上帝模式,你用过吗?

    [摘要] 上帝模式,即"God Mode",是电脑中隐藏的一个简单的文件夹窗口,包含了系统所有的设置,控制面板.界面个性化.辅助功能选项等方方面面的控制设置,用户只需通过这一个窗口 ...

  6. java责任链模式_java中责任链模式详解和使用方法

    顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计模式属于行为 ...

  7. java中的原型模式_java中的原型模式理解

    //测试类 public class TestPrototype { /** * @param args */ public static void main(String[] args) { She ...

  8. java 中策略模式_JAVA中的策略模式

    现在我们有一个虚基类-鸭子(abstract Duck). 有真鸭子,野鸭子,橡皮鸭子继承了该类.虚基类有swing方法,毕竟游泳是所有的鸭子都应有的功能.还有一个虚方法display,这个方法在子类 ...

  9. mixin模式 python_Python中的mixin模式

    MixIn和继承的关系 面向对象三大特征,继承.封装.多态.第一次看到MixIn的时候,弄不懂这个和继承有什么关系/区别.首先,继承是父亲和儿子的关系,而python minxin是混入的意思.虽然, ...

最新文章

  1. 目标10亿部?苹果AR眼镜有望明年登场!传搭载Mac级处理器、4K显示屏
  2. 写一个函数返回参数二进制中 1 的个数
  3. 唯品会API网关设计与实践--转
  4. 相当全面:推荐系统干货总结
  5. SpringBoot_web开发-【实验】-登陆拦截器
  6. linux命令学习-4-lsof
  7. Zookeeper面试题锦集
  8. hdu2115: I Love This Game
  9. windows查询每个线程占用的内存_C#多线程
  10. 【有容云案例系列】基于Jenkins和Kubernetes的CI工作流
  11. OCR识别身份证及营业执照图片(Java版)
  12. 通达信画线文件是在服务器吗,通达信画线工具的使用说明★★★★
  13. MySQL 数据库命名规范.PDF
  14. 微信小程序 转发功能的实现
  15. 怎么自己制作返利机器人教程分享
  16. linux redis-trib.rb,linux - redis-trib.rb 命令详解
  17. ept技术_EPT和VPID简介 - osc_3xz91vxi的个人空间 - OSCHINA - 中文开源技术交流社区
  18. html 列表页 后台添加分类 后台添加商品 商品详情页 注册页面 首页
  19. MSM8998(高通835处理器)外接指纹识别传感器linux驱动如何与设备树进行匹配
  20. Router中如何设置光标以全屏十字架显示

热门文章

  1. iscsi自动login磁盘
  2. 看看你是如何被QQ监视的!
  3. ACPI对接Windows操作系统
  4. wangeditor 自定义 表情
  5. 使用Visual Studio 2022中的Web实时预览设计Web窗体应用程序
  6. MADlib——基于SQL的数据挖掘解决方案(11)——回归之线性回归
  7. 模拟退火算法与遗传算法求解多目标优化问题的算法实现(数学建模)
  8. 浅谈tracert路由跟踪功能,tracert数据包解析
  9. 读《哈佛大学的 500 个数独游戏》
  10. H5 利用media实现自适应布局