程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 編寫高質量代碼改善C#程序的157個建議——建議49:在Dispose模式中應提取一個受保護的虛方法,

編寫高質量代碼改善C#程序的157個建議——建議49:在Dispose模式中應提取一個受保護的虛方法,

編輯:C#入門知識

編寫高質量代碼改善C#程序的157個建議——建議49:在Dispose模式中應提取一個受保護的虛方法,


建議49:在Dispose模式中應提取一個受保護的虛方法

在標准的Dispose模式中,真正的IDisposable接口的Dispose方法並沒有做實際的清理工作,它其實是調用了下面的這個帶bool參數且受保護的的虛方法:

        /// <summary>
        /// 非密封類修飾用protected virtual
        /// 密封類修飾用private
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
      //省略代碼 }

之所以提供這樣一個受保護的虛方法,是因為考慮了這個類型會被其他類型繼承的情況。如果類型存在一個子類,子類也許會實現自己的Dispose模式。受保護的虛方法用來提醒子類:必須在自己的清理方法時注意到父類的清理工作,即子類需要在自己的釋放方法中調用base.Dispose方法。

    public class DerivedSampleClass : SampleClass
    {
        //子類的非托管資源
        private IntPtr derivedNativeResource = Marshal.AllocHGlobal(100);
        //子類的托管資源
        private AnotherResource derivedManagedResource = new AnotherResource();
        //定義自己的是否釋放的標識變量
        private bool derivedDisposed = false;

        /// <summary>
        ///重寫父類Dispose方法
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (derivedDisposed)
            {
                return;
            }
            if (disposing)
            {
                // 清理托管資源
                if (derivedManagedResource != null)
                {
                    derivedManagedResource.Dispose();
                    derivedManagedResource = null;
                }
            }
            // 清理非托管資源
            if (derivedNativeResource != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(derivedNativeResource);
                derivedNativeResource = IntPtr.Zero;
            }
            //調用父類的清理代碼
            base.Dispose(disposing);
            //讓類型知道自己已經被釋放
            derivedDisposed = true;
        }
    }

    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()
        {
        }
    }


如果不為類提供這個受保護的虛方法,很有可能讓開發者設計子類的時候忽略掉父類的清理工作。所以要在類型的Dispose模式中提供一個受保護的虛方法。

 

 

轉自:《編寫高質量代碼改善C#程序的157個建議》陸敏技

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved