Asp.Net教程,WinForm教程,Asp.Net MVC,vs2008教程,vs2010教程,Silverlight技术,源码下载,Asp.Net视频教程
全站热门标签
vs2010 Silverlight 存储过程 水晶报表 ADO.NET JavaScript LINQ AjaxPro DataGridView 面向对象 Extjs GridView XML DevExpress HTML教程 Oracle jQuery 分页 GDI+ Visual C++2010 MySQL Office2010 WPF MVC Dojo WCF4.0 VB.NET Sql2005 textbox cookie WCF WinForm Discuz!NT SQL经典语句 T-SQL checkbox ASPxGridView F# asp.net SQL VS2008新特性 DropDownList Access TreeView Ajax VS2008 页面执行时间 Flex 字符串 回调 VB2005 DataSet C#时间 ASP.NET性能优化 用户在线检测 动画
尚未分类 LINQ教程 Enterprise技术 性能优化/调试 水晶报表与打印 安全与加密 图形图像 文件处理基础教程 Web Services 内置对象 控件示例 正则表达式\采集 ADO.NET 缓存\泛型\线程 XML技术 Url重写\静态页 vs2008综合教程
当前位置: 主页 > ASP.NET教程 > 基础教程 >

IDisposable接口和析构函数

时间:2010-05-09 01:16来源: 作者:admin 点击:

其实这是一个老话题了,只是刚才做程序的时候突然发现自己有些概念有点模糊,所以做了一个测试如下:

这段代码是MSDN中的例子修改而来。
using System;
using System.ComponentModel;

// The following example demonstrates how to create
// a resource class that implements the IDisposable interface
// and the IDisposable.Dispose method.

public class DisposeExample
{

    public class MyDisposableMember: IDisposable
    {
        private bool disposed = false;
        private string info;

        public MyDisposableMember(string _info)
        {
            info = _info;
            System.Diagnostics.Debug.WriteLine("\tMyDisposableMember:" + info);
        }

        public void Dispose()
        {
            System.Diagnostics.Debug.WriteLine("\tDispose:" + info);
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if(!this.disposed)
            {
                if(disposing)
                {
                }
              
            }

            disposed = true;          
        }

        ~MyDisposableMember()      
        {
            System.Diagnostics.Debug.WriteLine("\t~MyDisposableMember():" + info);
            Dispose(false);
        }
    }



    // A base class that implements IDisposable.
    // By implementing IDisposable, you are announcing that  
    // instances of this type allocate scarce resources.
    public class MyResource: IDisposable
    {
        // Track whether Dispose has been called.
        private bool disposed = false;
        private string info;
        MyDisposableMember member;

        // The class constructor.
        public MyResource(string _info)
        {
            info = _info;
            System.Diagnostics.Debug.WriteLine("MyResource:" + info);
            member = new MyDisposableMember("member-" + _info);
        }

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            System.Diagnostics.Debug.WriteLine("Dispose:" + info);
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue  
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the  
        // runtime from inside the finalizer and you should not reference  
        // other objects. Only unmanaged resources can be disposed.
        private void Dispose(bool disposing)
        {
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed  
                // and unmanaged resources.
                if(disposing)
                {
                    // Dispose managed resources.
                    member.Dispose();
                }
              
                // Call the appropriate methods to clean up  
                // unmanaged resources here.
                // If disposing is false,  
                // only the following code is executed.

                member = null;
            }

            disposed = true;          
        }

        // Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method  
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~MyResource()      
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            System.Diagnostics.Debug.WriteLine("~MyResource():" + info);
            Dispose(false);
        }
    }
    public static void Main()
    {
        // Insert code here to create
        // and use the MyResource object.  
        MyResource mr = new MyResource("mr");
        mr.Dispose();

        new MyResource("hang");

        using(MyResource m = new MyResource("using"))
            System.Diagnostics.Debug.WriteLine("ready to exit using statement");

        System.GC.SuppressFinalize(mr);
    }

/*
运行结果如下:
    
MyResource:mr
    MyDisposableMember:member-mr
Dispose:mr
    Dispose:member-mr
MyResource:hang
    MyDisposableMember:member-hang
MyResource:using
    MyDisposableMember:member-using
ready to exit using statement
Dispose:using
    Dispose:member-using
    ~MyDisposableMember():member-hang
~MyResource():hang

*/
从运行结果我们可以分析出如下的结果:

1.如果调用Dispose进行释放,则系统不会调用其析构函数
2.如果是系统自动释放的,则不会调用其Dispose函数,也就是说,.net垃圾收集器其实不认识 IDisposable接口。
3.在类析构过程中,会先释放其中的成员,最后再调用类的析构函数本身。

这里第3点需要说明一下,这是和C++中区别很大的地方,在C++中所有的释放都需要类的析构函数来进行,也就是在C++的析构函数中,所有的成员都是可用而且有效的。但是在C#中就会有区别了,因为C#的类析构函数调用之前,系统就会进行托管成员对象的清理工作。从生命周期的观点来看,类成员的生命周期必须包含在类的生命周期之内,C#这么做没有问题,但是问题时在于程序经常需要在析构函数中使用类的成员,所以就出现了异常情况:在析构函数中使用的类成员已经被析构了!也就是说,同样在析构函数范围内,C++包含的寓意是“析构=无效”,但是在C#的析构函数范围中,“析构 != 无效”。

由此,我们明白了为什么一些代码检查的软件会建议我们实现IDisposable时候,像例子中那样要自定义一个Dispose(bool disposing)了。
 

(责任编辑:admin)
Tags:接口 析构函数
责任编辑:admin
返回顶部
------分隔线----------------------------
推荐内容
骆驼户外男 真皮磨砂日常休闲鞋 低帮 2011秋冬新款 专柜正品特价 骆驼户外男 真皮磨砂日常休闲鞋 低帮 2011秋冬新款 专柜正品特价
  • C#中Dictionary、ArrayList、Hashtable和数组Array

    C# 集合类 Array Arraylist List Hashtable Dictionary Stack Queue 1.数组是固定大小的,不能伸缩。虽然S...

  • PictureBox内的图片拖动功能

    当 PictureBox内的图片太大,超过PictureBox边框时可以用下面的方法来实现, 通过重绘来实现 : Code bool wselected = f...

  • Directory.GetCurrentDirectory和Application.

    System.IO.Directory.GetCurrentDirectory()方法用于获得应用程序当前工作目录。 System.Windows.Forms....

  • IConvertible接口

    IConvertible 接口 定义特定的方法,这些方法将实现引用或值类型的值转换为具有等效值的公共语言运行库类型。 命名空间: System 程序集: msc...

  • 将枚举类型的数据绑定到控件

    .NET Framework中的数据绑定有几个很酷的功能。你不仅可以将集合、数组、DataTable和DataView对象绑定到列表绑定(list-bound)...

  • 数组求和算法系列

    一直想写一个数组求和算法系列博客,但由于自己算法能力有限,完成不了,只能完成其中简单的部分,难的部分希望有园友愿意和我一起完成。在写这篇博客的过程中借用了别人的...

  • 细说C#构造器

    1.实例构造器和类 构造器是允许将类型的实例化为良好的状态的一种特殊方法。 当创建一个类型的实例时: 1)为实例的字段分配内存。 2)初始化对象的附加字段(类型...

  • 对象的序列化存入数据库,与反序列化

    开发过程中遇到一个问题,我想到的解决方法是将一个dictionary字典如何存如数据库,读出来的时候还是这个字典 然后接触到对象的序列化与反序列化。开始打算序列...

  • const限定修饰符用法总结(常量,指针,迭代器,函数参数,成员函数)

    const限定修饰符用法总结(常量,指针,迭代器,函数参数,成员函数)...

  • 回文算法

    回文:针对于字符串的中间位置两边对应位置相等。对于长度为n的字符串,需要比较的次数为N/2。 用2种方法对该应用实现算法如下: 1:采用字符串的substrin...

  • c# MACD算法实现

    c# MACD算法实现...

  • c#自杀程序的关键方法

    public static void TestForKillMyself() { string bat=@@echooff :tryagain del%1 if...

  • 对泛型进行反射

    今天在用反射的时候突然想到,之前从来没有对泛型对象进行反射,故决定尝试一下 首先要获取某个泛型类的Type,键入如下代码: Typet=Type.GetType...

  • C#遍历文件夹

    DirectoryInfo FileName = new DirectoryInfo( @D:\ ); 2 foreach (DirectoryInfo Nex...

  • .NET对象序列化—TimeSpan

    在 WebServices 中, TimeSpan 不能作为系统的 TimeSpan 作为参数,在客户端会生成新的 TimeSpan 类。 一、问题重现 创建一...