C# 析构函数和dispose模式

来源:互联网 发布:淘宝达人是干什么的 编辑:程序博客网 时间:2024/05/17 15:35

析构函数

类可以用用析构函数(destructor),它可以在一个类的实例不在被引用的时候执行一些操作,以清除或释放非托管资源。非托管资源是指类似用Win32 API或非托管内存块获取的文件句柄这样的资源。使用.NET资源是无法获取它们的,因此如果我们只用.NET类。是不需要编写太多的析构函数的。

        关于析构函数要注意以下几点。

·每个类只能有一个析构函数。

·析构函数不能有参数。
·析构函数不能有访问修饰符。

·析构函数名称与类名相同,但是前面加一个波浪符。

·析构函数只能作用于类的实例。因此没有静态的析构函数。

·不能再代码中显示调用析构函数。相反,当垃圾回收器分析代码并认为代码中不存在指向对象的可能路径时,系统会在垃圾回收中调用析构函数。

使用析构函数是一些重要的原则如下:

·不要在不需要时实现析构函数。这会严重影响性能;

·析构函数应该只释放对象拥有的外部资源。

·析构函数不应该访问其他对象,因为无法认定这些对象是否已经被销毁。

标准dispose模式

标准dispose模式包含以下特点。

·包含非托管资源的类应该事先IDisposable接口,后者包含单一方法Dispose。Dispose包含释放资源的清除代码。

·如果代码使用完了这些资源且希望将他们释放,应该在程序代码中调用Dispose方法。注意,这是在你的代码中调用Dispose。

·你都累还应该实现一个析构函数,在其中调用Dispose方法,以防止之前没有调用该方法。你想讲所有的清除代码放到Dispose中,并在使用完资源时调用。以防止Dispose没有调用,类的析构函数也应该调用Dispose。而另一方面如果调用了Dispose,你就希望通知垃圾回收器不要在调用析构函数,因为已经由Dispose执行了清除操作。

析构函数和Dispose代码应该遵循以下原则。

·修改函数和Dispose方法的逻辑应该是,如果由于某种原因代码没有调用Dispose,那么修改函数应该调用它,并释放资源。

·在Dispose方法的最后应该调用GC.SuppressFinalize方法,通知CLR不要电泳该对象的析构函数,因为清除工作已经完成。

·在Dispose中实现这些代码。这样多次调用该方法是安全的。也就是说代码要这样写:如果该方法已经被调用,那么任何后续调用都不回执行额外的工作,也不会抛出任何异常。


标准Dispose模式,要点:

·Dispose方法有两个重载:一个是public的,一个protected的。protected的重载包含实际的清除代码。

·public 版本可以在代码中显示调用以执行清除工作。它会调用protected版本。
·析构函数调用protected版本、

`protected版本的bool参数通知方法是被析构函数或是其他代码调用。这一点很重要,因为结果不同所执行的操作略有不同。

案例

 class Class1 : IDisposable
    {

        bool disposed = false;
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        ~Class1()
        {
            Console.WriteLine("析构函数释放了");
            Dispose(false);
        }

        protected virtual void Dispose(bool disposing)
        {

            if (disposed == false)
            {
                if (disposed == true)
                {
                    //由Dispose是释放
                }
                else if (disposed == false)
                {
                    //由析构函数释放
                }
                disposed = true;
            }
        }

        static void Main(string[] args) {
            Class1 c = new Class1();
            Console.ReadKey();
        }
    }

原创粉丝点击