C#-Dispose 和 Close 的区别

Dispose Close 的区别

Dispose Close 基本上是一样的 ,Close 是给不熟悉 Dispose 的开发者设计的 ; 对于某些类来说 ,Close 更有逻辑性 .
.NET 的一些 class 只提供 Close, 且派生自 IDisposable 并隐藏了 Dispose 方法 ; 这些 class, 它们其实显式的实现了 IDisposable.
Close 被设计成 public , 并且在 Close 里面显式实现了接口 IDisposable 中的 Dispose 方法 ; 而这个方法里面 , 又调用了方法 Dispose(bool)( 此为虚函数 , 使用 protected 修饰符 ), 所以你从这些类 ( 只提供 Colse 的类 ) 中继承的话就必须实现 Dispose(bool) 这个方法 ; 所以如果你要实现一个有 Close 的类的话 , 也需实现 Dispose(bool);
        提示:编译器在编译析构函数时,会隐式的把析构函数编译为Finalize()方法的对应代码,确保执行父类的Finalize()方法.
1
// 例1
abstract   class  SysClass : IDisposable
{
    
private IntPtr m_unmanagedResource;
    
private Bitmap m_bitmap;
    
private bool m_disposed = false;

    
public SysClass()
    
{
        m_unmanagedResource 
= Marshal.AllocCoTaskMem(100);
        m_bitmap 
= new Bitmap(50,50);
    }


    
void IDisposable.Dispose() //显式实现
    {
        Dispose(
true); //调用 Dispose(bool)
           //不要再去浪费资源的去执行析构函数了,上面已经执行过啦
        GC.SuppressFinalize(this);
    }


    
//实现Dispose(bool),注意,此为虚函数,使用protected修饰符
       //protected的好处是不让用户有可能主动去调用 Dispose(false)
    protected virtual void Dispose(bool isDisposing) 
    
{
        
if(!m_disposed)
        
{
            
if(isDisposing)
            
{
                
//在此处释放托管资源
                m_bitmap.Dispose(); //m_bitmap就是托管资源
            }

            
//在此处释放非托管资源
            Marshal.FreeCoTaskMem(m_unmanagedResource);
            m_disposed 
= true;
        }

    }


    
public void Close()
    
{
        ((IDisposable)
this).Dispose();
    }


    
~SysClass()
    
{
        Dispose(
false);
    }

}


class  MyClass : SysClass  // 实现一个自己类里的Close
{
    
private IntPtr m_anotherMemory;
    
private Bitmap m_anotherImage;
    
private bool m_disposed = false;

    
public MyClass()
    
{
        m_anotherMemory 
= Marshal.AllocCoTaskMem(20);
        m_anotherImage 
= new Bitmap(25,25);
    }


    
//实现Dispose(bool)
    
//如果传入false,就只释放非托管资源;传入true,全部释放
    protected override void Dispose(bool isDisposing)
    
{
        
if(!m_disposed)
        
{
            
if(isDisposing)
            
{
                
//在此处释放托管资源
                m_anotherImage.Dispose();//m_anotherImage就是托管资源
            }

            
//在此处释放非托管资源
            Marshal.FreeCoTaskMem(m_anotherMemory);
            
base.Dispose(isDisposing);//子类会执行父类的构造函数,这里还需释放父类的
            m_disposed = true;
        }

    }

    
    
~MyClass()
    
{
        Dispose(
false);
    }

}


public   static   void  Main( string [] args)
{
    SysClass sc 
= new MyClass();
    sc.Close(); 
//正确
    sc.Dispose(); //错误
    ((IDisposable)sc).Dispose(); //正确
}
MyClass 类和它的父类都使用了双保险 (Dispose+ 析构函数 ) 来释放资源 . 如果用户调用了 Dispose(), 不会再调用析构函数 (SuppressFinalize 的缘故 ); 但如果用户忘记调用 Dispose(), 就自然会转到析构函数而析构函数本来就具有释放托管资源的能力 , 所以只要将 false 传给 Dispose 就行了 .
 
2007-09-08添加
要实现一个具有Dispose功能的类,首先该类要继承自一个具有Close()方法的类,并实现一个Dispose(bool),此函数是一个Protected型的重载函数.
实现过程:
1) Close()里面其实调用了IDisposable接口的Dispose()方法;
2) Dispose方法(此方法需显式实现)里调用了Dispose(bool)方法
3) Dispose(bool)方法里实现了托管和非托管资源的释放.
4) (可选)最好在类的析构函数里实现Dispose(false)方法(flase标记的作用是只释放非托管资源)
5) (可选)子类的释放自身资源的同时也要释放父类中的资源(如果父类在构造函数中生成了资源).我觉得,就算父类的构造函数中没有生成资源,也最好在子类中实现一下.(见上例 base.Dispose(isDisposing);)
6) 注意使用类的对象调用Dispose()方法时的写法.(见上例)

你可能感兴趣的:(.net,String,Class,编译器)