我们已经讨论过,处理一个占用了非托管资源对象是很重要的。现在是时候 来讨论如何写代码来管理这些类占用的非内存资源了。一个标准的模式就是利用 .Net框架提供的方法处理非内存资源。你的用户也希望你遵守这个标准的模式。也就是通过实现IDisposable接口来释放非托管的资源,当然是在用户记得调用 它的时候,但如果用户忘记了,析构函数也会被动的执行。它是和垃圾回收器一 起工作的,确保在一些必要时候,你的对象只会受到因析构函数而造成的性能损 失。这正是管理非托管资源的好方法,因此有必要彻底的弄明白它。
处 在类继承关系中顶层的基类应该实现IDisposable接口来释放资源。这个类型也 应该添加一个析构函数,做为最后的被动机制。这两个方法都应该是用虚方法来 释放资源,这样可以让它的派生类重载这个函数来释放它们自己的资源。派生类 只有在它自己须要释放资源时才重载这个函数,并且一定要记得调用基类的方法 。
开始时,如果你的类使用了非内存资源,则一定得有一个析构函数。 你不能指望你的用户总是记得调用Dispose方法,否则当他们忘记时,你会丢失 一些资源。这或许是因为他们没有调用Dispose的错误,但你也有责任。唯一可 以确保非内存资源可以恰当释放的方法就是创建一个析构函数。所以,添加一个 析构函数吧!
当垃圾回收器运行时,它会直接从内存中移除不用析构的垃 圾对象。而其它有析构函数的对象还保留在内存中。这些对象被添加到一个析构 队列中,垃圾回收器会起动一个线程专门来析构这些对象。当析构线程完成它的 工作后,这些垃圾对象就可以从内存中移除了。就是说,须要析构的对象比不须 要析构的对象在内存中待的时间要长。但你没得选择。如果你是采用的这种被动 模式,当你的类型占用非托管资源时,你就必须写一个析构函数。但目前你还不 用担心性能问题,下一步就保证你的用户使用更加简单,而且可以避免因为析构 函数而造成的性能损失。
实现IDisposable接口是一个标准的模式来告诉 用户和进行时系统:你的对象占有资源而且必须及时的释放。IDisposable接口 只有一个方法:
public interface IDisposable
{
void Dispose( );
}
实现IDisposable.Dispose()方法有责 任完成下面的任务:
1、感知所有的非托管资源。
2、感知所有的 托管资源(包括卸载一些事件)。
3、设置一个安全的标记来标识对象已经 被处理。如果在已经处理过的对象上调用任何方法时,你可以检验这个标记并且 抛出一个ObjectDisposed的异常。
4、阻止析构。你要调用 GC.SuppressFinalize(this)来完成最后的工作。