接口IDisposable的用法
C#的每一个类型都代表一种资源,而资源又分为两类:
- 托管资源 由CLR管理分配和释放的资源,即从CLR里new出来的对象。
- 非托管资源 不受CLR管理的对象,如Windows内核对象,或者文件、数据库连接、套接字、COM对象等。
如果类型用到了非托管资源,或者需要显式释放托管资源,那么需要让类型继承接口IDisposable。记住:如果类型需要显式释放资源,那么一定要继承IDisposable接口。如:
class SampleClass:IDisposable
{
private IntPtr nativeResource = Marshal.AllocHGlobal();//非托管资源
private Bitmap bitmap = new Bitmap(, );//托管资源
private bool isDisposed = false; //实现IDisposable中的Dispose方法
public void Dispose( )
{
Dispose(true);
GC.SuppressFinalize(this);//通知垃圾回收器不用再调用终结器
}
//不必要的方法,只是为了符合其他语言的规范
public void Close()
{
Dispose();
}
//必须的,防止程序员忘记显示调用Dispose方法(隐式清理)
~SampleClass()
{
Dispose(false);
}
//非密封类修饰用protected virtual,提醒子类必须实现自己的清理方法时注意到父类的清理工作
protected virtual void Dispose(bool isDisposing)
{
if(isDisposed)
{
return;
}
if(isDisposing)
{
//清理托管资源
if(bitmap != null)
{
bitmap.Dispose();
bitmap = null;
}
}
//清理非托管资源
if(nativeResource!=IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
isDisposed = false;
} public void SamplePublicMethod()
{
if(isDisposed)
{
throw new ObjectDisposedException("SampleClass", "SampleClass is disposed");
}
//代码
}
}
继承IDisposable接口,可以使用using语法糖。在using语句代码块内,可以使用声明的对象,当语句离开代码块后,系统自动释放资源:
//使用using方法,当语句离开代码块后,using内的对象自动释放
using (SampleClass sample = new SampleClass())
{
//……
}
//以上代码相当于下面的代码
SampleClass sample0 = new SampleClass();
try
{
//……
}
finally
{
sample0.Dispose();
}
在SampleClass中,存在一个终结器(C++中叫析构器)。其意义在于,调用者可能并不会主动调用Dispose方法,而终结器会被垃圾回收器调用调用,所以它作为释放资源的补救措施。
在CLR中,每new一个对象时,就会为该对象在堆上分配内存,如果不再被引用,就会回收它们的内存。如果没有实现IDisposable接口的类型对象,垃圾回收器会直接释放对象所占内存;如果实现了,每次创建对象时,CLR会将该对象的一个指针放到终结列表中,垃圾回收器在回收对象前会首先将终结列表中的指针放入一个freachable队列。同时,CLR会分配一个线程管理freachable队列,调用对象终结器,只有此时,对象才会被真正标识为垃圾,并在下一次进行垃圾回收时释放对象所占内存。即:实现IDisposable接口的类型,至少要经过两次垃圾回收才能真正释放掉内存。其中Dispose方法中的GC.SuppressFinalize()方法用于在显示释放资源后,通知垃圾回收器不用再调用终结器(隐式回收)释放资源。
在实现IDisposable接口时,其Dispose()方法并没有做实际的清理工作,但提供了带bool参数的受保护的虚方法。因为该类型可能被其他类继承,如果子类实现自己的Dispose模式,受保护的虚方法可以提醒子类:在实现自己的清理方法时,需要注意父类的清理工作(base.Dispose方法)。
真正撰写资源释放代码的虚方法有一个bool参数,但是在显示释放资源(true)与隐式释放资源(false)调用中传入的参数不同。表明:隐式清理时,只需要处理非托管资源就行。托管资源中的普通类型不需要手动清理,而非普通类型需要手动清理。
Dispose模式设计思路:如果调用者显示调用了Dispose方法,那么类型按部就班释放自己的全部资源,然后通知垃圾回收器不需要再释放(GC.SuppressFinalize()方法);而忘记调用Dispose方法,那么类型就假定自己的所有托管资源会全部交给垃圾回收器回收,不需要手动清理。
接口IDisposable的用法的更多相关文章
- 实现接口IDisposable的示例
想使用using(...), 如: using (Getter process = new Getter()) { //... } 就必须给类实现接口IDisposable public sealed ...
- psycopg2接口的基本用法
转载自:http://zhiwei.li/text/2012/02/05/psycopg2接口的基本用法/ 与其他实现了DB API 2.0协议的其他数据库用户基本一致. import psycopg ...
- 编写高质量代码改善C#程序的157个建议——建议46:显式释放资源需继承接口IDisposable
建议46:显式释放资源需继承接口IDisposable C#中的每一个类型都代表一种资源,资源分为两类: 托管资源:由CLR管理分配和释放的资源,即从CLR里new出来的对象. 非托管资源:不受CLR ...
- C#中IDisposable的用法
在Net中,由GC垃圾回收线程掌握对象资源的释放,程序员无法掌控析构函数的调用时机.对于一些非托管资源,比如数据库链接对象等,需要实现IDisposable接口进行手动的垃圾回收.那么什么时候使用Id ...
- C#中IDisposable的用法-垃圾回收
在Net中,由GC垃圾回收线程掌握对象资源的释放,程序员无法掌控析构函数的调用时机.对于一些非托管资源,比如数据库链接对象等,需要实现IDisposable接口进行手动的垃圾回收.那么什么时候使用Id ...
- Comparable接口和Comparator接口的不同用法
两者都可用来在定义比较方法,然后用在排序中. Comparable是类本身继承的接口 Comparator实在类外定义一个排序的类 比较而言,觉得Comparator更灵活一些,但是Comparabl ...
- [原创]Java中使用File类的list方法获取一定数量的文件:FilenameFilter接口的特殊用法
前言:有时候我们可能会遇到这样一个问题:需要遍历一个包含极多文件的文件夹,首先想到的肯定是使用File.list()方法,该方法返回一个String[],但是如果文件达到几亿呢?这个时候我们就需要分批 ...
- Java中Comparable接口和Comparator接口的简单用法
对象比较器 1.Comparable接口 此接口强行对实现它的每个类的对象进行整体排序,这种排序成为类的自然排序,类的compareTo方法称为类的自然比较方法. 代码示例 import java.u ...
- Java EE开发平台随手记5——Mybatis动态代理接口方式的原生用法
为了说明后续的Mybatis扩展,插播一篇广告,先来简要说明一下Mybatis的一种原生用法,不过先声明:下面说的只是Mybatis的其中一种用法,如需要更深入了解Mybatis,请参考官方文档,或者 ...
随机推荐
- 服务器选型:x86 vs 小型机谁更胜一筹?
市场上关于X86 和小型机的争论从来就没有停止过,在以往的印象当中,x86服务器在中低端形成了统治之势,而小型机则在关键性应用领域(金融.证券.政府等)享有王者地位.但是随着X86服务器的不断发展,这 ...
- [ML] Gradient Descend Algorithm [Octave code]
function [theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters) m = length(y); % n ...
- 《OpenCL异构并行编程实战》补充笔记散点,第一至四章
▶ 总体印象:适合 OpenCL 入门的书,有丰富的代码和说明,例子较为简单.先把 OpenCL 代码的基本结构(平台 → 设备 → 上下文 → 命令队列 → 创建缓冲区 → 读写缓冲区 → 编译代码 ...
- UNITY polygon collider不随物体旋转
U3D中的一般包围框如 boxcollider, meshcollider, capsule collider等都会随物体旋转而旋转.然而polygon collider却不会. 补充:原来所有2D包 ...
- 编程, 细心永远都不嫌多(记录java连接数据库的一个错误)
最近在学习Java连接oracle数据库操作, 无意间一个小问题, 浪费了一个下午和半个晚上去找这个错误, 本来可以做更多的事情的, 现将这个错误贴出来, 每次看到, 定将勉励! .......... ...
- 读取指定路径的Properties文件
1.读取项目内的properties文件,项目内的properties文件一般都放在resource文件夹下面, 通过getClassLoader().getResourceAsStream()来获取 ...
- 01d-1: 算法分析
- react-navigation 3.x版本的安装以及react-native-gesture-handler配置
一.安装依赖,使用npm或yarn命令,3.x版本必须安装react-native-gesture-handler react-navigation react-native-gesture-hand ...
- 自定义对象实现copy,遵守协议<NSCopying, NSMutableCopying>
自定义对象实现copy,步骤 1.需要遵守NSCopying协议 2.实现协议中的- (id)copyWithZone:(NSZone *)zone 3.在- (id)copyWithZone:(NS ...
- IDEA00 IDEA知识点汇总
一.从头搭建IDEA开发环境 https://mp.weixin.qq.com/s/6jXHzkU8JfubhDsQJbwl8Q 1 下载最新版IDEA 1.1 官网下载安装 1.2 专业版激活 2 ...