需要明确一下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. android获取元素路径,Appium元素定位(name、classname、相对路径、绝对路径\、list)...
  2. 在docker中构建普通java程序_Docker入门-构建第一个Java程序
  3. Linux学习笔记 Day 4~5
  4. Hadoop DFS源码研究之---Hadoop RPC机制
  5. 认认真真推荐几个机器学习和Python类的公众号
  6. C++ 贪吃蛇 小游戏
  7. css 列 布局,CSS二列三列布局
  8. Mint-UI 报错提示缺少“raf.js / vue-lazyload / vue-popup” - 解决办法
  9. 【Hbase】 Region Server 各种意外退出
  10. window.createPopup()用法以及短消息提示框代码
  11. nlog自定义文件名
  12. java学习笔记(5)
  13. python选取tensor某一维_Python按维数操作多维张量,Pytorch,对,Tensor,维度
  14. uni-app官方教程学习手记 1
  15. Bootstrap-table 如何合并相同单元格
  16. Ubuntu 18.04 安装后的美化与软件安装
  17. 正态总体参数的假设检验
  18. 如何制作Android.9图片
  19. 免费把pdf转换成excel
  20. org.apache.poi Excel列与行都是动态生成的_网络爬虫:Python动态网页爬虫2种技术方式及示例...

热门文章

  1. Python3版本以上知识点归纳之一
  2. 基于51单片机的智能水表水流量计流量报警器温度设计方案原理图
  3. VsCode设置快捷输入
  4. CentOS7安装配置FTP
  5. 2021年熔化焊接与热切割考试资料及熔化焊接与热切割考试技巧
  6. 第 十七 章迭代器、生成器和经典协程
  7. js中的原型与原型链
  8. Dynamic Fusion 总结(根据论文:《DynamicFusion: Reconstruction and Tracking of Non-rigid Scenes in Real-Time》
  9. 网络黑客攻防学习平台之基础关第七题
  10. 如何在html中加入音效,为你的html5网页添加音效示例