托管对象指的是.net可以自动进行回收的资源,主要是指托管对象在堆上分配的内存资源。托管资源的回收工作是不需要人工干预的,有.net运行库在合适的时间进行回收。(手动回收GC.Collect)
非托管对象指.net不知道如何回收的资源,最常见的一类非托管资源是包装操作系统资源的对象,例如文件、窗口、网络连接、数据库连接、画刷、图标等。这类资源,垃圾回收器在清理的时候会调用Object.Finalize()方法。默认情况下,方法是空的,对于非托管对象在此方法中需要编写回收非托管对象的代码,以便垃圾回收器正确回收。(例如我们通常打开文件、图片等后需要进行Close()或者Dispose()去释放)。
本来如果按照上面做法,非托管资源也能够由垃圾回收器进行回收,但是非托管资源一般是有限的,比较宝贵的,而垃圾回收器是由CRL自动调用的,这样就无法保证及时的释放掉非托管资源,因此定义了一个Dispose()方法,让使用者能够手动的释放非托管资源。Dispose()方法释放类的托管资源和非托管资源,使用者手动调用此方法后,垃圾回收器不会对此类实例再次进行回收。Dispose()方法是由使用者调用的,在调用时,类的托管资源和非托管资源肯定都未被回收,所以可以同时回收两种资源。
Microsoft为非托管资源的回收专门定义了一个接口:IDisposable,接口中只包含一个Dispose()方法。任何包含非托管资源的类,都应该继承此接口。
在一个包含非托管资源的类中,关于资源释放的标准做法是:
(1)继承IDisposable()接口;
(2)实现Dispose()方法,在其中释放托管资源和非托管资源,并将对象本身从垃圾回收器中移除(垃圾回收器不在回收此资源);
(3)实现类析构函数,在其中释放非托管资源。
这样做的目的是为了更好的提高程序性能,避免内存泄漏,小数据量往往体现不出来,当数据量庞大时就会出现内存不足以及System.OutOfMemoryException:“Exception_WasThrown”的错误。
下一章会讲如何实现释放非托管资源的类。