• IDisposable接口和析构函数


    IDisposable接口和析构函数

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

    这段代码是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)了。

  • 相关阅读:
    CentOS 6找不到partprobe命令的解决方法
    RTL源码归类与路径
    拓扑排序
    Char、AnsiChar、WideChar、PChar、PAnsiChar、PWideChar 的区别
    Delphi Byte与数据类型之间的转换
    Delphi byte[]转换为int
    Delphi Byte数组与Int String之间的相互转换
    delphi TTcpClient TTcpServer分析
    Delph7中TcpClient和TcpServer用法分析
    动态数组的使用
  • 原文地址:https://www.cnblogs.com/BigTall/p/105553.html
Copyright © 2020-2023  润新知