Effective C# 原则18:实现标准的处理(Dispose)模式
2009-02-19 08:16:44 来源:WEB开发网如果派生类有另外的清理任务,就让它实现Dispose方法:
public class DerivedResourceHog : MyResourceHog
{
// Have its own disposed flag.
private bool _disposed = false;
protected override void Dispose( bool isDisposing )
{
// Don't dispose more than once.
if ( _disposed )
return;
if ( isDisposing )
{
// TODO: free managed resources here.
}
// TODO: free unmanaged resources here.
// Let the base class free its resources.
// Base class is responsible for calling
// GC.SuppressFinalize( )
base.Dispose( isDisposing );
// Set derived class disposed flag:
_disposed = true;
}
}
注和意,派生类和基类都有一个处理状态的标记,这完全是被动的。重制的标记掩盖了在处理时任何可能发生的错误,而且是单一的类型处理,而不是处理构成这个对象的所有类型。(译注:就是基类与子类各自标记一个,互不影响。)
你应该被动的写处理方法和析构函数,处理对象可能以任何顺序发生,你可能会遇到这种情况:你的类中某个成员在你调用Dispose方法以前已经被处理过了。你没有看到这种情况是因为Dispose()方法是可以多次调用的。如果在一个已经被处理过的对象上调用该方法,就什么也不发生。析构函数也有同样的规则。任何对象的引用存在于内存中时,你不用检测null引用。然而,你引用的对象可能已经处理掉了,或者它已经析构了。
这就引入用了一个非常重要的忠告:对于任何与处理和资源清理相关的方法,你必须只释放资源! 不要在处理过程中添加其它任何的任务。你在处理和清理中添加其它任务时,可能会在对象的生存期中遇到一些严重而繁杂的问题。对象在你创建它时出生,在垃圾回收器认领它时死亡。你可以认为当你的程序不能再访问它们时,它们是睡眠的。你无法访问对象,无法调用对象的方法。种种迹象表明,它们就像是死的。但对象在宣布死亡前,析构函数还有最后一气。析构函数什么也不应该做,就是清理非托管资源。如果析构函数通过某些方法让对象又变得可访问,那么它就复活了。(译注:析构函数不是用户调用的,也不由.Net系统调用,而是在由GC产生的额外线程上运行的) 它又活了,但这并不好。即使是它是从睡眼中唤醒的。这里有一个明显的例子:
更多精彩
赞助商链接