1. 程式人生 > >【轉】編寫高質量代碼改善C#程序的157個建議——建議46:顯式釋放資源需繼承接口IDisposable

【轉】編寫高質量代碼改善C#程序的157個建議——建議46:顯式釋放資源需繼承接口IDisposable

cep nag pre 回收 如果 win name 實現 每一個

建議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