• 【转】编写高质量代码改善C#程序的157个建议——建议47:即使提供了显式释放方法,也应该在终结器中提供隐式清理


    建议47:即使提供了显式释放方法,也应该在终结器中提供隐式清理

    在标准的Dispose模式中,我们注意到一个以~开头的方法,如下:

            /// <summary>
            /// 必须,防止程序员忘记了显式调用Dispose方法
            /// </summary>
            ~SampleClass()
            {
                //必须为false
                Dispose(false);
            }

    这个方法叫做类型的终结器。提供类型终结器的意义在于,我们不能奢望类型的调用者肯定会主动调用Dispose方法,基于终结器会被垃圾回收这个特点,它被用作资源释放的补救措施。

    在.NET中每次使用new操作符创建对象时,CLR都会为该对象在堆上分配内存。对于没有继承IDisposable接口的类型对象,垃圾回收器则会直接释放对象所占用的内存:而对于实现了Dispose模式的类型,每次创建对象的时候,CLR都会将该对象的一个指针放到终结列表中,垃圾回收器在回收该对象的内存前,首先将终结列表中的指针放到一个freachable队列中。同时,CLR还会分配专门的线程读取freachable队列,并调用对象的终结器,只有这个时候对象才会真正被识别为垃圾,并且在下一次进行垃圾回收时释放对象所占的内存。

    可见,实现了Dispose模式的类型对象,起码要经过两次垃圾回收才能真正地被回收掉,应为垃圾回收机制会安排CLR调用终结器。基于这个特点,如果我们的类型提供了显式释放的方法来减少一次垃圾回收,同时也可以在终结器中提供隐式清理,以避免调用者忘记调用该方法而带来的资源泄漏。

    注意:有的文档中,终结器也称为析构器。析构器的叫法沿袭了C++中的称谓,因为两者形式非常接近,但两者实现机制还是不太一致,所以后来微软确定这个方法在C#中的名称为终结器。

    如果调用者已经调用Dispose方法进行了显式地资源释放,那么,隐式资源释放(就是终结器)就没有必要再运行了。FCL中的类型GC提供了静态方法SuppressFinalize来通知垃圾回收器这一点。

            /// <summary>
            /// 实现IDisposable中的Dispose方法
            /// </summary>
            public void Dispose()
            {
                //必须为true
                Dispose(true);
                //通知垃圾回收机制不再调用终结器(析构器)
                GC.SuppressFinalize(this);
            }

    转自:《编写高质量代码改善C#程序的157个建议》陆敏技

  • 相关阅读:
    [转]window.open居中
    WebService实例一
    开发步骤
    ubuntu命令
    ubuntu如何添加软件源
    WebService学习笔记
    android.view.WindowManager$BadTokenException: Unable to add window token null is not for an application
    Dialog的使用
    区分Activity的四种加载模式
    在android 中导入项目后 包出现错误
  • 原文地址:https://www.cnblogs.com/farmer-y/p/7991197.html
Copyright © 2020-2023  润新知