【转】C# IDisposable
原文地址:http://dearymz.blog.163.com/blog/static/20565742009102745358396/
IDisposable接口的解释为:定义一种释放分配的资源的方法。此接口的主要用途是释放非托管资源。当不再使用托管对象时,垃圾回收器会自动释放分配给该对象的内存。但无法预测进行垃圾回收的时间。另外,垃圾回收器对窗口句柄或打开的文件和流等非托管资源一无所知。将此接口的 Dispose 方法与垃圾回收器一起使用来显式释放非托管资源。当不再需要对象时,对象的使用者可以调用此方法。
class MyDispose : System.IDisposable { private bool disposed = false; // 保证多次调用Dispose方式不会抛出异常 #region IDisposable 成员 //可以被客户直接调用 public void Dispose() { //必须以Dispose(true)方式调用,以true告诉Dispose(bool disposing)函数是被客户直接调用的 Dispose(true); // 告诉垃圾回收器从Finalization队列中清除自己,从而阻止垃圾回收器调用Finalize方法. GC.SuppressFinalize(this); } #endregion // 无法被客户直接调用 // 如果 disposing 是 true, 那么这个方法是被客户直接调用的,那么托管的,和非托管的资源都可以释放 // 如果 disposing 是 false, 那么函数是从垃圾回收器在调用Finalize时调用的,此时不应当引用其他托管对象所以,只能释放非托管资源 protected virtual void Dispose(bool disposing) { //检查是否已经调用Dispose if (disposed) return; if (disposing) { // TODO: 在这里释放托管资源 } // TODO: 在这里释放非托管资源 disposed = true; } // 析构函数自动生成 Finalize 方法和对基类的 Finalize 方法的调用.默认情况下,一个类是没有析构函数的,也就是说,对象被垃圾回收时不会被调用Finalize方法 ~MyDispose() { // 为了保持代码的可读性性和可维护性,千万不要在这里写释放非托管资源的代码 // 必须以Dispose(false)方式调用,以false告诉Dispose(bool disposing)函数是从垃圾回收器在调用Finalize时调用的 Dispose(false); } }
以上代码中带参数的Dispose方法可以写成private,但如果要写成protected 最好也加上virtual,以便子类定制。但绝对不能写成public的,否则很可能用户在使用时传进来错误的false参数,从而造成内存管理混乱。
不论什么类的析构函数编译后签名都变成统一的protected virtual void Finalize(), 这是编译器在后台做的手脚。GC通过Finalize方法来在回收对象前尝试释放资源并进行其他清理操作。有了Finalize方法的保护,即使用户不小心忘记调用Dispose方法,GC在自动调用Finalize时也会正常的执行资源回收,防止泄露发生。

浙公网安备 33010602011771号