標籤:man prot style public ++ == ret span source
建議46:顯式釋放資源需繼承介面IDisposable
C#中的每一個類型都代表一種資源,資源分為兩類:
託管資源:由CLR管理分配和釋放的資源,即從CLR裡new出來的對象。
非託管資源:不受CLR管理的對象,如Windows核心對象,或者檔案、資料庫連接、通訊端、COOM對象等。
如果我們的類型使用了非託管資源,或者需要顯示地釋放託管資源,那麼就需要讓類型繼承介面IDisposable,這毫無例外。這相當於告訴調用者,類型資源是需要顯示釋放資源的,你需要調用類型的Dispose方法。
一個標準的繼承了IDisposable介面的類型應該像下面這樣去實現,這種實現我們稱為Dispose模式:
public class SampleClass : IDisposable { //示範建立一個非託管資源 private IntPtr nativeResource = Marshal.AllocHGlobal(100); //示範建立一個託管資源 private AnotherResource managedResource = new AnotherResource(); private bool disposed = false; /// <summary> /// 實現IDisposable中的Dispose方法 /// </summary> public void Dispose() { //必須為true Dispose(true); //通知記憶體回收機制不再調用終結器(析構器) GC.SuppressFinalize(this); } /// <summary> /// 不是必要的,提供一個Close方法僅僅是為了更符合其他語言(如 /// C++)的規範 /// </summary> public void Close() { Dispose(); } /// <summary> /// 必須,防止程式員忘記了顯式調用Dispose方法 /// </summary> ~SampleClass() { //必須為false Dispose(false); } /// <summary> /// 非密封類修飾用protected virtual /// 密封類修飾用private /// </summary> /// <param name="disposing"></param> protected virtual void Dispose(bool disposing) { if (disposed) { return; } if (disposing) { // 清理託管資源 if (managedResource != null) { managedResource.Dispose(); managedResource = null; } } // 清理非託管資源 if (nativeResource != IntPtr.Zero) { Marshal.FreeHGlobal(nativeResource); nativeResource = IntPtr.Zero; } //讓類型知道自己已經被釋放 disposed = true; } public void SamplePublicMethod() { if (disposed) { throw new ObjectDisposedException("SampleClass", "SampleClass is disposed"); } //省略 } } class AnotherResource : IDisposable { public void Dispose() { } }
繼承IDisposable介面也為實現文法糖using帶來了便利。如:
using (SampleClass cl = new SampleClass()){ //省略}
等價於:
SampleClass cl;try{ cl == new SampleClass(); //省略}finally{ cl.Dispose();}
如果存在兩個類型一致的對象,using還可以這樣使用:
using (SampleClass c1 = new SampleClass(),c2=new SampleClass()){ //省略}
如果兩個類型不一致,則可以這樣使用:
using (SampleClass c1 = new SampleClass())using (SampleAnotherClass c2 = new SampleAnotherClass()){ //省略}
轉自:《編寫高品質代碼改善C#程式的157個建議》陸敏技
【轉】編寫高品質代碼改善C#程式的157個建議——建議46:顯式釋放資源需繼承介面IDisposable