zoukankan      html  css  js  c++  java
  • 【转】编写高质量代码改善C#程序的157个建议——建议46:显式释放资源需继承接口IDisposable

    建议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个建议》陆敏技

  • 相关阅读:
    杨辉三角(hdu2032)——有待完善
    求平均成绩(hdu2023)
    绝对值排序(2020)——笔记待完善
    母牛的故事(hdu2018)——笔记待完善
    29.数据结构---栈,队列,数组,链表,哈希表
    16.PR将视频剪辑成任意形状
    28.集合1------List
    IDEA选中多行代码向左右移动缩进
    27.集合1------Collection
    IDEA显示单个文件结构
  • 原文地址:https://www.cnblogs.com/farmer-y/p/7988612.html
Copyright © 2011-2022 走看看