CLR提供了自动内存管理。Managed memory不需要我们显式地释放。当进行Garbage Collection时,会自动释放。
但是,managed memory仅仅是许多种系统资源中的一种。除了managed memory之外的其他需要显式地释放的资源,被称为unmanaged resources,比如打开的文件描述符,打开的数据库连接等。
CLR提供了释放unmanaged resources的机制。System.Object中声明了一个virtual 方法 Finalize,该方法类似C++中的析构函数,当一个object的内存被回收时,GC会调用Finalize方法释放unmanaged resources。重写了Finalizer的类型也叫做Finalizable类型。
public class ComplexResourceHolder : IDisposable { private IntPtr buffer; // unmanaged memory buffer private SafeHandle resource; // disposable handle to a resource public ComplexResourceHolder(){ this.buffer = ... // allocates memory this.resource = ... // allocates the resource } ~ ComplexResourceHolder(){ ReleaseBuffer(buffer); // release unmanaged memory } }
但是使用finalizer有不好的地方
.Net Framework提供了System.IDisposable接口,通过实现该接口的Dispose方法,我们可以手动调用该方法,这样就可以自己控制unmanaged resources的释放时间。Framework也提供了GC.SuppressFinalize方法告诉GC该对象已经被手动disposed,不需要finalized。这样,该对象的内存就可以被尽快地回收。
.Net推荐的IDisposable接口实现方式如下
public class ComplexResourceHolder : IDisposable { private IntPtr buffer; // unmanaged memory buffer private SafeHandle resource; // disposable handle to a resource public ComplexResourceHolder(){ this.buffer = ... // allocates memory this.resource = ... // allocates the resource } // Implement IDisposable. // Do not make this method virtual. // A derived class should not be able to override this method. public void Dispose(){ 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); } // 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. ~ComplexResourceHolder(){ Dispose(false); } // 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. protected virtual void Dispose(bool disposing){ // release unmanaged memory ReleaseBuffer(buffer); // release other disposable objects if (disposing){ if (resource!= null) resource.Dispose(); } } }
Reference:
1. http://msdn.microsoft.com/zh-cn/library/system.idisposable.dispose(v=vs.110).aspx
2. http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx
原文:http://www.cnblogs.com/wangguangxin/p/4155932.html