C#中垃圾收集器的出现意为着,通常不需要担心不再需要的对象,只要让这些对象的所有引用都超出作用域,并允许垃圾收集器在需要时释放资源即可。但是,垃圾收集器不知道如何释放未托管的资源(例如文件句柄、网络链接和数据库链接)。托管类在封装对未托管资源的直接或间接引用时,需要制定专门的规则,确保未托管资源在回收类的一个实例时释放。
在定义一个类时,可以使用两种机制来自动释放未托管资源。这些机制常常放在一起实现,因为每个机制都为问题解决提供了不同的解决方法。这两种机制是:
声明一个析构函数,作为类的一个成员
在类中实现System.IDisposable接口
实现IDisposable接口和析构函数
利用运行库强制执行的析构函数,但析构函数的执行是不确定的,而且,由于垃圾收集器的工作方式,它会给运行库增加不可接受的系统开销。
IDisposable接口提供了一种机制,允许类的用户控制释放资源的时间,但需要确保执行Dispose().一般情况下,做好的的方法是执行这两种机制,获得这两种机制的有点,克服其缺点。
public class ResourceHolder : IDisposable
{
private bool isDispose = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}protected virtual void Dispose(bool disposing)
{
if (!isDispose)
{
if (disposing)
{
//Cleanup managed objects by calling their Dispose() methods
}
//Cleanup unmanaged objects
}
isDispose = true;
}~ResourceHolder()
{
Dispose(false);
}
}可以看出,Dispose()有第二个protected重载方法,它带一个bool参数,这是真正完成清理工作的方法。Dispose(bool)由析构函数和IDisposable.Dispose()调用。这个方法的重点是确保所有的清理代码都放在一个地方。