本帖最后由 茹化肖 于 2013-9-25 09:49 编辑
- class DisposePattern :IDisposable
- {
- private System.IO.FileStream fs = new System.IO.FileStream("test.txt", System.IO.FileMode.Create);
- ~DisposePattern()
- {
- Dispose(false);
- }
- IDisposable Members#region IDisposable Members
- public void Dispose()
- {
- //告诉GC不需要再调用Finalize方法,
- //因为资源已经被显示清理
- GC.SupdivssFinalize(this);
- Dispose(true);
- }
- #endregion
- protected virtual void Dispose(bool disposing)
- {
- //由于Dispose方法可能被多线程调用,
- //所以加锁以确保线程安全
- lock (this)
- {
- if (disposing)
- {
- //说明对象的Finalize方法并没有被执行,
- //在这里可以安全的引用其他实现了Finalize方法的对象
- }
- if (fs != null)
- {
- fs.Dispose();
- fs = null; //标识资源已经清理,避免多次释放
- }
- }
- }
- }
- 在注释中已经有了比较清楚的描述,另外还有一点需要说明:如果DisposePattern类是派生自基类B,而B是一个实现了Dispose的类,那么DisposePattern中只需要override基类B的带参的Dispose方法即可,而不需要重写无参的Dispose和Finalize方法,此时Dispose的实现为:
- class DerivedClass : DisposePattern
- {
- protected override void Dispose(bool disposing)
- {
- lock (this)
- {
- try
- {
- //清理自己的非托管资源,
- //实现模式与DisposePattern相同
- }
- finally
- {
- base.Dispose(disposing);
- }
- }
- }
- }
复制代码 当然,如果DerivedClass本身没有什么资源需要清理,那么就不需要重写Dispose方法了,正如我们平时做的一些对话框,虽然都是继承于System.Windows.Forms.Form,但我们常常不需要去重写基类Form的Dispose方法,因为本身没有什么非托管的咚咚需要释放。 了解GC的脾性在很多时候是非常必要的,起码在出现资源泄漏问题的时候你不至于手足无措。我写过一个生成excel报表的控件,其中对excel对象的释放就让我忙活了一阵。如果你做过excel开发的话,可能也遇到过结束excel进程之类的问题,特别是包装成一个供别人调用的库时,何时释放excel对象以确保进程结束是一个关键问题。当然,GC的内部机制非常复杂,还有许多内容可挖,但了解所有细节的成本太高,只需了解基础,够用就好。 |