在.net 編程環境中,系統的資源分為托管資源和非托管資源。
托管資源:
Net平台中,CLR為程序員提供了一種很好的內存管理機制,使得程序員在編寫代碼時不要顯式的去釋放自己使用的內存資源(這些在先前C和C++中是需要程序員自己去顯式的釋放的)。這種管理機制稱為GC(garbage collection)。GC的作用是很明顯的,當系統內存資源匱乏時,它就會被激發,然后自動的去釋放那些沒有被使用的托管資源(也就是程序員沒有顯式釋放的對象)。
所以托管就是.net framework 負責幫你管理內存及資源釋放,不需要自己控制,當然對象只針對托管資源(部分引用類型), 不回收非托管資源。
像數組,用戶定義的類、接口、委托,object,字符串等引用類型,棧上保存着一個地址而已,當棧釋放后, 即使對象已經沒有用了,但堆上分配的內存還在,只能等GC收集時才能真正釋放 ;但注意int,string,float,DateTime之類的值類型,GC會自動釋放他們占用的內存,不需要GC來回收釋放
那么非托管的資源怎么釋放回收呢?
非托管資源:
對於非托管資源,GC只能跟蹤非托管資源的生存期,而不知道如何去釋放它。這樣就會出現當資源用盡時就不能提供資源能夠提供的服務,windows的運行速度就會變慢。比如當你鏈接了數據庫,用完后你沒有顯式的釋放數據庫資源,如果還是不斷的申請數據庫資源,那么到一定時候程序就會拋出一個異常。
所以,當我們在類中封裝了對非托管資源的操作時,我們就需要顯式,或者是隱式的釋放這些資源。 在.Net中釋放非托管資源主要有2種方式,Dispose,Finalize, 而Finalize和Dispose方法分別就是隱式和顯式操作中分別使用到的方法。
例如文件流,數據庫的連接,系統的窗口句柄,打印機資源等等,
當你讀取文件之后,就需要對各種Stream進行Dispose等操作。比如 SqlDataReader 讀取數據完畢之后,需要 reader.Dispose();等
Finalize一般情況下用於基類不帶close方法或者不帶Dispose顯式方法的類,也就是說,在Finalize過程中我們需要隱式的去實現非托管資源的釋放,然后系統會在Finalize過程完成后,自己的去釋放托管資源。
在.NET中應該盡可能的少用析構函數釋放資源,MSDN2上有這樣一段話:實現 Finalize 方法或析構函數對性能可能會有負面影響,因此應避免不必要地使用它們。用 Finalize 方法回收對象使用的內存需要至少兩次垃圾回收。所以有析構函數的對象,需要兩次,第一次調用析構函數,第二次刪除對象。而且在析構函數中包含大量的釋放資源代碼,會降低垃圾回收器的工作效率,影響性能。
所以對於包含非托管資源的對象,最好及時的調用Dispose()方法來回收資源,而不是依賴垃圾回收器。