safehandle 和析构函数

safehandle 是一种析构机制,她和析构函数有什么分别。

首先要理解析构函数。析构函数在.net中是没有顺序的,因此你不能假定另一个对象的析构函数在你之后运行,哪怕它是你的成员!如果你的成员也有析构函数,那么你能做什么,什么不应该做?

第一,你不应该假设它没清理,而去试图清理它。合理的做法是它应该自己实现dispose模式,你在dispose(false)段落可以调用它的dispose()函数.因为dispose是可多次重入的,因此不会有问题。当然你也可以不理他。

第二,一个实现了dispose的.net对象,外部应该怎样看它?不应该把它所控制的资源看作非托管资源,既然他实现了dispose,也就是“有自行管理”的,因此应该在dispose(false)段落调用。这是我对dispose模式的理解。dispose模式分两类资源,一类是托管,一类是非托管。托管和非托管并不是纯粹站在.net角度出发,而是应该理解为“自己管理”和“其他对象管理”的差别。你的对象自己打开文件,就自己负责关闭,而其他对象,包括成员对象,他们控制的资源就由他们控制,在当前立场上看,都是“受托管的”。

这样的好处是,我可以分别控制每一个实现dispose模式的对象成员的控制时机,而dispose(false)也就是析构函数,能够作为防御性代码,帮我把忘记的对象资源清理掉。当然也有坏处,如果你希望dispose就是关闭所有资源,它就没有这个效果。但是dispose有两种实现模式,一种是没有析构函数做组合的,可以采用这种统一模式,也不需要依赖防御性代码了,当然这个清理任务就交给你了。

然后是safehandle,safehandle据说有经过优化,但是它也不会抢先在析构函数阶段运行,在我测试中是这种情况。因此,我不知道优化在那里了。只是添加了一种模式,比析构函数更舵控制,毕竟是外部独立的类,而且系统已经针对多种资源提供了恰当的子类,可惜没有针对com对象资源。

总的来说,最佳实践是:

1.如果safehandle子类有的系统资源,如句柄,非托管内存等等,用safehandle 模式。

2.如果子成员正确实现了dispose,用带析构函数的dispose模式。

3.如果子成员没有实现dispose,但是控制了相关资源,也就是你要负责子对象相关资源的显式控制,千万别用析构函数清理,因为析构函数阶段,子成员可能已经把它关联的资源给释放掉了(未必以正确的方式,只是对资源失去控制力),你无法再清理。因为GC对任意对象的析构函数调用顺序是不确定的。(这一状况只能要求你在编程阶段正确调用dispose,而绝不能遗忘调用,否则就有资源泄漏。com for .net就是如此设计的)

4.其他情况,可以用析构函数做防御性编程。

5.dispose的实现方式要规范。

规范的dispose该注意哪些,这里补充一下:

        private bool disposedValue = false; // 要检测冗余调用

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)。
                    //这里应该包含成员对象的dispose
                    //safehandle.Dispose();

                }

                // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
                // TODO: 将大型字段设置为 null。
                //这里是自身管理的一些资源的释放
                CloseFile();
                app = null;

                disposedValue = true;
            }
        }

        //TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
         ~Excel()
        {
            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
            Dispose(false);
        }

        // 添加此代码以正确实现可处置模式。
        void IDisposable.Dispose()
        {
            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
            Dispose(true);
            // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
            //如果dispose(false) 段落没有内容,可以补充下面语句,反之得注释掉
            //这个语句目的是取消析构的运行。假设没有内容,也不需要写析构函数了,所以是多此一举
             GC.SuppressFinalize(this);
        }
时间: 2025-01-16 18:44:51

safehandle 和析构函数的相关文章

SafeHandle和Dispose z

SafeHandle最大的意义是封装一个托管资源且本身会执行.NET中的资源释放模式(所谓的Dispose Pattern),这样,开发者在使用非托管资源时,不可以不需要执行繁琐的资源释放模式,而直接使用SafeHandle就可以了,另外SafeHandle继承自CriticalFinalizerObject类型,CLR对其的Finalize方法有特殊优化. 整个.NET Framework内有许多SafeHandle,比如.NET 4新加的SafeBuffer(在System.Runtime.

C++基础3 类:构造 拷贝 析构函数,

为什么会出现构造函数 与 析构函数 [email protected]:~/c++$ cat main.cpp  #include <iostream> #include <stdlib.h> #include <string.h> using namespace std; class Test { public: void init() { a = 1; b = 2; } private: int a; int b; }; int main() { Test arr[

C++ 构造函数和析构函数

构造函数: 作用: 1)分配空间:分配非静态数据成员的存储空间 2)初始化成员:初始化非静态数据成员 分配空间: 1)含有指针变量,需要程序员显式申请空间(使用new申请) 2)非指针变量:由系统自动分配空间 初始化成员: 1)使用赋值语句初始化:一般的变量 2)使用表达式表初始化:一般的变量 +  Const成员,引用成员,对象成员 调用时机:在定义对象的时候,系统自动调用构造函数 1)对象被创建时,自动调用构造函数 Coord p1(1); Coord p2=1;  //此时也会调用构造函数

构造函数和析构函数是否可以被重载

构造函数可以被重载,因为构造函数可以有多个且可以带参数. 析构函数不可以被重载,因为析构函数只能有一个,且不能带参数.

C++:析构函数

一.什么是析构函数 析构函数是类中一种特殊的成员函数,但其功能和构造函数是相反的,当对象结束其生命周期时,系统会自动调用该对象的析构函数进行清理工作(如释放内存中分配给该对象的空间,关闭打开的文件等).另外析构函数没有返回值,不需要参数,也不能被重载且一个类中有且只能有一个析构函数.但和构造函数相似,析构函数的函数名和类名相同,只不过需要在函数名向加上一个~. 语法:~ 类名(){/*...析构函数体...*/} 特别注意: ? 如果用户没有显式地在类中定义析构函数,编译器会在类中生成一个默认的

关于PHP面向对象中—类的定义与对象的实例化操作以及构造、析构函数的特殊用法

类的定义与对象的实例化操作 <?php //类里面的成员是属于对象的class Hero{    public $name;//成员变量    //成员属性(存在于强类型语言中)    protected $blood;    private $attack;    //成员方法    function skill(){        echo "$this->name<br>control";            }} $s = new Hero();//造

面向对象中的继承、封装、构造与析构函数

构造函数:是一种特殊的方法.主要用来在创建对象时初始化对象,即为对象成员变量赋值初始值,总与new运算符一起使用在创建对象的           语句中.两根下划线开头,construct     作用:为对象成员变量赋值初始值 类的构造方法,是一个魔术方法     * 自动的被调用(可以被内部进行使用并调用)     * 不用申明,相当于默认一个没有任何执行语句的构造函数     * 会自动返回一个当前类的对象     * 一个类中有且只有一个构造函数     * 构造函数可以带参数,通常是给

构造函数和析构函数?它们有什么作用? 面向对象的特征有哪些?

析构函数:构造函数是在对象实例化时自动执行,而析构函数在对象被销毁时自动执行. 构造函数:当类被实例化时,会自动执行的函数 构造函数有什么作用:我们在使用类的过程中,有时需要立即为实例化对象的多个字段父子,如果通过手工,会带来很多不可预测的问题,而如果在对象创建过程中自动执行,则会带来很多方便. 析构函数有什么作用:默认情况下,php仅释放对象属性所占用的内存,并不销毁对象相关的资源,而利用析构函数在使用一个对象之后执行代码来清除内存,并将对象从内存中销毁 面向对象的特征有哪些? 封装.继承.多

python中的构造函数和构造函数和析构函数的作用

构造函数和构造函数和析构函数都属于python中的特殊方法 其中的"__del__"就是一个析构函数了,当使用del 删除对象时,会调用他本身的析构函数,另外当对象在某个作用域中调用完毕,在跳出其作用域的同时析构函数也会被调用一次,这样可以用来释放内存空间