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()方法.
提示:编译器在编译析构函数时,会隐式的把析构函数编译为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)
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修饰符
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(); //正确
}
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()方法时的写法.(见上例)