非托管资源的释放
与C++一样,C#可以定义析构函数。但C#的析构函数主要用于释放托管资源。在Net中,由GC垃圾回收线程掌握对象资源的释放,程序员无法掌控析构函数的调用时机。为了完全掌控非托管资源的释放,Net提供一个IDisposable接口。
问题:Finalize()和Dispose()之间的区别?
最简单的解释是:Finalize自动释放资源,Dispose()用于手动释放资源。Finalize很像C++的析构函数,在代码中的实现也很像,但它的调用过程却大不相同。例如类A中实现了Finalize函数,在A的一个对象a被创建时,它的指针被插入到一个finalization链表中,在GC运行时,它将查找finalization链表中的对象指针,如果此时a已经是垃圾对象的话,它会被移入到一个freachable队列中,最后GC会调用一个高优先级线程,此线程专门负责遍历freachable队列并调用队列中所有对象的Finalize方法,至此,对象a中的非托管资源才得到释放,而a所占用的内存资源则必须等到下一次GC才能释放,所以一个实现了Finaliza方法的对象必须等两次GC才能被完全释放。
由于Finalize是由GC负责调用,可以说是一种自动的释放方式。里面牵涉到两个问题:1是无法确定GC何时运作,有可能很长时间不释放对象资源。2是会带来微妙的依赖性问题,因为负责的线程并不保证对象的Finalize调用的顺序。可见自动释放资源不能满足我们的需求,因为我们不能显式地调用它(它只能由GC调用),而且具有依赖性的问题,我们需要更准确地控制资源的释放。
Dispose方法:
Dispose是提供给我们显式调用的方法。
using (){}能自动调用Dispose方法。
在计算机科学中,内存泄漏(memory leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏与许多其他问题有着相似的症状,并且通常情况下只能由那些可以获得程序源代码的程序员才可以分析出来。然而,有不少人习惯于把任何不需要的内存使用的增加描述为内存泄漏,严格意义上来说这是不准确的。
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显式释放的内存。应用程序一般使用malloc,calloc,realloc等函数(C++中使用new操作符)从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。