• 【转】编写高质量代码改善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个建议》陆敏技

  • 相关阅读:
    ASP.NET中的ViewState
    (标记)Spring.Net+NHibenate+Asp.Net mvc +ExtJs 系列 By 似水流年
    C#中类的定义
    苹果CMS搭建影视网站教程
    Java之冒泡排序
    Java之数组扩容
    Linux之netstat命令基本使用
    Linux之systemctl命令基本使用
    Oracle11g R2 安装教程(非常详细 )
    Linux之firewall防火墙开启和关闭
  • 原文地址:https://www.cnblogs.com/farmer-y/p/7991711.html
Copyright © 2020-2023  润新知