C#中的IDisposable模式用法詳解
本文實例講述了C#中IDisposable模式的用法,針對垃圾資源的回收進行了較為詳細的講解。分享給大家供大家參考之用。具體方法如下:
首先,對於垃圾回收而言,在C#中,托管資源的垃圾回收是通過CLR的Garbage Collection來實現的,Garbage Collection會調用堆棧上對象的析構函數完成對象的釋放工作;而對於一些非托管資源,比如數據庫鏈接對象等,需要實現IDisposable接口進行手動的垃圾回收。那麽什麽時候使用Idisposable接口,以及如何使用呢?
先來參考一下如下代碼:
public interface IDisposable { void Dispose(); } public class DisposablClass : IDisposable { //是否回收完畢 bool _disposed; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ~DisposableClass() { Dispose(false); } //這裏的參數表示示是否需要釋放那些實現IDisposable接口的托管對象 protected virtual void Dispose(bool disposing) { if(_disposed) return; //如果已經被回收,就中斷執行 if(disposing) { //TODO:釋放那些實現IDisposable接口的托管對象 } //TODO:釋放非托管資源,設置對象為null _disposed = true; } }
Dispose()方法
當需要回收非托管資源的DisposableClass類,就調用Dispoase()方法。而這個方法不會被CLR自動調用,需要手動調用。
~DisposableClass(),析構函數
當托管堆上的對象沒有被其它對象引用,GC會在回收對象之前,調用對象的析構函數。這裏的~DisposableClass()析構函數的意義在於告訴GC你可以回收我,Dispose(false)表示在GC回收的時候,就不需要手動回收了。
虛方法Dispose(bool disposing)
通過此方法,所有的托管和非托管資源都能被回收。參數disposing表示是否需要釋放那些實現IDisposable接口的托管對象。
如果disposings設置為true,就表示DisposablClass類依賴某些實現了IDisposable接口的托管對象,可以通過這裏的Dispose(bool disposing)方法調用這些托管對象的Dispose()方法進行回收。
如果disposings設置為false,就表示DisposableClass類依賴某些沒有實現IDisposable的非托管資源,那就把這些非托管資源對象設置為null,等待GC調用DisposableClass類的析構函數,把這些非托管資源進行回收。
另外,以上
把Dispose(bool disposing)方法設置為protected virtual的原因是希望有子類可以一起參與到垃圾回收邏輯的設計,而且還不會影響到基類
。比如有這樣的一個子類:
public class SubDisposableClass : DiposableClass { private bool _disposed; //表示是否已經被回收 protected override void Dispose(bool disposing) { if(!_disposed) //如果還沒有被回收 { if(disposiing) //如果需要回收一些托管資源 { //TODO:回收托管資源,調用IDisposable的Dispose()方法就可以 } //TODO:回收非托管資源,把之設置為null,等待CLR調用析構函數的時候回收 _disposed = true; } base.Dispose(disposing);//再調用父類的垃圾回收邏輯 } }
在.NET 2.0之前,如果一個對象的析構函數拋出異常,這個異常會被CLR忽略。但.NET 2.0以後,如果析構函數拋出異常就會導致應用程序的崩潰。所以,保證析構函數不拋異常變得非常重要
。
還有,Dispose()方法允許拋出異常嗎?答案是否定的。
如果Dispose()方法有拋出異常的可能,那就需要使用try/catch來手動捕獲
。以下是考慮Dispose()方法有異常可能的寫法:
public class DisposableClass : IDisposable { bool _disposed; ...... protected virtual void Dispose(bool disposing) { if(_disposed) return; if(disposing) { //TODO:調用托管資源的Dispose()方法進行垃圾回收 } try { _channelFactory.Close(); //關閉的時候可能會有異常 } catch(Exception ex) { _log.Warn(ex);//記錄日誌 try { _channelFactory.Abort();//丟棄的時候可能會有異常 } catch(Exception cex) { _log.Warn(cex);//記錄日誌 } } _channelFactory = null; _disposed = true; } }
總結:
當我們自定義的類及其業務邏輯中引用某些托管和非托管資源,就需要實現IDisposable接口,實現對這些資源對象的垃圾回收。
希望本文所述對大家實現高效率的C#程序設計能夠有所幫助。
除聲明外,跑步客文章均為原創,轉載請以鏈接形式標明本文地址C#中的IDisposable模式用法詳解
本文地址: http://www.paobuke.com/develop/c-develop/pbk23539.html
相關內容
C#實現FTP客戶端的案例ò????éDˉ′????ó???¢μ????????¢?òMessageBoxEx日常收集C#接口知識(知識全面)C#實現控制攝像頭的類C#修改及重置電腦密碼DirectoryEntry實現方法C#確保只有一個實例在運行的方法C#遍歷List並刪除某個元素的方法C# WinForm捕獲未處理的異常實例解析
C#中的IDisposable模式用法詳解