本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议 进行许可。
在VB.NET框架中,类没有真正意义的析构函数,但是有两种方式可以实现析构函数的功能:一个是Finalize方法,用于被动的释放资源;另一个是Dispose方法,可以主动的释放资源。
Finalize方法由垃圾回收系统(GC)自动调用。使用Finalize方法需要注意以下要点:
1. 延迟调用特性
由于垃圾回收是由.NET框架通过一个独立的线程自动调用的,因此当所有指向对象的变量都设置为Nothing之后,Finalize方法不会立即被调用。
2. 访问限制
一方面,托管对象的资源释放是由垃圾回收系统完成的,在Finalize方法中不必管理其它托管对象的释放工作;另一方面,也不要在Finalize方法中访问任何托管对象,因为这些托管对象很可能已经被销毁。在Finalize方法中应该总是释放那些非托管对象(如文件句柄等)的资源。
3. 调用限制
永远不要在程序中主动调用Finalize方法,调用Finalize方法的唯一方式是将引用对象的变量设置为Nothing。
由于Finalize方法的种种限制,特别是延迟调用特性,我们不得不使用一种更主动的方式来释放资源,那就是实现IDisposable.Dispose方法。使用Dispose方法需要注意以下要点:
1. 立即执行
与Finalize的延迟调用特性不同,Dispose方法被设计成使用者主动调用并立即执行。这是一种可控制的释放资源的方法。
2. 托管资源的释放
除了非托管对象的释放工作之外,Dispose还要负责托管对象的释放(注释1) ,这一点Finalize方法是做不到的。
3. 调用不受限制
程序中可以多次调用对象的Dispose方法。通常情况下,只有第一次调用时释放资源。
如何选择释放资源的方法呢?是实现Finalize还是实现Dispose?
如果不介意延迟调用并且对象内部仅有非托管资源需要释放,实现Finalize方法是很好的选择。选择Finalize方法完全取决于我们对延迟调用的容忍程度,试问当我们想要关闭一个文件时系统却没有及时响应,这样的情况是否允许?
如果对象内部存在其它托管对象并且这些托管对象实现了Dispose方法,那么实现Dispose方法用于释放内部的托管对象将是唯一的选择。因为只有在Dispose方法中才可以调用其内部对象的Dispose方法。
如果要实现的类是一个基类,并且不想让继承类的释放过程过于复杂,请使用Dispose-Finalize模式实现释放资源的功能。
注释1:释放托管对象的资源
有两个方法可以释放托管对象的资源:如果托管对象实现了IDisposable.Dispose方法,调用这个方法;然后将指向托管对象的变量设置为Nothing。可以用下面的方法一站式处理: