三種最常的方法以下: 數據庫
1. 析構函數;(由GC調用,不肯定何時會調用) 函數
2. 繼承IDisposable接口,實現Dispose方法;(能夠手動調用。好比數據庫的鏈接,SqlConnection.Dispose(),由於若是及時釋放會影響數據庫性能。這時候會用到這個,再如:文件的打開,若是不釋放會影響其它操做,如刪除操做。調用Dispose後這個對象就不能再用了,就等着被GC回收。) 性能
3. 提供Close方法。(相似Dispose可是,當調用完Close方法後,能夠經過Open從新打開) this
析構函數不能顯示調用,而對於後兩種方法來講,都須要進行顯示調用才能被執行。而Close與Dispose這兩種方法的區別在於,調用完了對象的Close方法後,此對象有可能被從新進行使用;而Dispose方法來講,此對象所佔有的資源須要被標記爲無用了,也就是此對象要被銷燬,不能再被使用。例如常見.Net類庫中的SqlConnection這個類,當調用完Close方法後,能夠經過Open從新打開一個數據庫鏈接,當完全不用這個對象了就能夠調用Dispose方法來標記此對象無用,等待GC回收。明白了這兩種方法的意思後,你們在往本身的類中添加的接口時候,不要歪曲了這二者意思。 spa
析構函數 對象
Dispose方法 繼承
Close方法 接口
意義 隊列
銷燬對象 資源
銷燬對象
關閉對象資源
調用方式
不能被顯示調用,在GC回收是被調用
須要顯示調用
或者經過using語句
須要顯示調用
調用時機
不肯定
肯定,在顯示調用或者離開using程序塊
肯定,在顯示調用時
下面提供一個模式來結合上面的 析構函數和Dispose方法。
public class BaseResource: IDisposable
{
//前面咱們說了析構函數其實是重寫了 System.Object 中的虛方法 Finalize, 默認狀況下,一個類是沒有析構函數的,也就是說,對象被垃圾回收時不會被調用Finalize方法
~BaseResource()
{
// 爲了保持代碼的可讀性性和可維護性,千萬不要在這裏寫釋放非託管資源的代碼
// 必須以Dispose(false)方式調用,以false告訴Dispose(bool disposing)函數是從垃圾回收器在調用Finalize時調用的
Dispose(false);
}
// 沒法被客戶直接調用
// 若是 disposing 是 true, 那麼這個方法是被客戶直接調用的,那麼託管的,和非託管的資源均可以釋放
// 若是 disposing 是 false, 那麼函數是從垃圾回收器在調用Finalize時調用的,此時不該當引用其餘託管對象因此,只能釋放非託管資源
protected virtual void Dispose(bool disposing)
{
// 那麼這個方法是被客戶直接調用的,那麼託管的,和非託管的資源均可以釋放
if(disposing)
{
// 釋放 託管資源
OtherManagedObject.Dispose();
}
//釋放非託管資源
DoUnManagedObjectDispose();
// 那麼這個方法是被客戶直接調用的,告訴垃圾回收器從Finalization隊列中清除本身,從而阻止垃圾回收器調用Finalize方法.
if(disposing)
GC.SuppressFinalize(this);
}
//能夠被客戶直接調用
public void Dispose()
{
//必須以Dispose(true)方式調用,以true告訴Dispose(bool disposing)函數是被客戶直接調用的
Dispose(true);
}
}
上面的範例達到的目的:
1/ 若是客戶沒有調用Dispose(),未能及時釋放託管和非託管資源,那麼在垃圾回收時,還有機會執行Finalize(),釋放非託管資源,可是形成了非託管資源的未及時釋放的空閒浪費
2/ 若是客戶調用了Dispose(),就能及時釋放了託管和非託管資源,那麼該對象被垃圾回收時,不回執行Finalize(),提升了非託管資源的使用效率並提高了系統性能
最後:
若是您的類中使用了非託管資源,則要考慮提供Close方法,和Open方法。並在您的Dispose方法中先調用 Close方法。
在使用已經 有類時,如SqlConnection。若是暫時不用這個鏈接,能夠考慮用Close()方法。若是不用了就考慮調用
Dispose()方法。