6

我目前正在修复 ac# 代码库,它没有很好的 Dispose 使用模式。

它是一个大型代码库,它是一个资源要求高的代码库,它在低级别使用了许多自定义的非托管 c++ 库。

我对处置模式有很好的了解。我花了一些时间来理解我认为关于这个问题的黄金标准文章:Joe Duffy 的处置文章

为了尽量减少代码重复,我们一直在考虑一些 dispose 辅助类,所以我的问题是:

如果一个基类实现了一个标准的 Dispose 模式,它是否应该允许共享它的 Dispose 标志,即。标记为受保护?

为了澄清,我的意思是在继承层次结构中是否应该只有一个布尔状态来定义对象实例是否已被释放,或者在继承阶梯的每个步骤中是否应该有一个私有布尔值?

MSDN 和上述链接中的示例在每个级别都设置了一个标志,但从未解释其背后的原因。我对这个问题有两种看法,你的想法和理由是什么?

4

4 回答 4

6

我会说不,它不应该共享旗帜。共享标志会为失败创造机会,而更好的封装可以防止这种机会。

例如,考虑在最基类上有一个只读的 Disposed 属性的场景。支持字段仅在基类的 Dispose(disposing) 方法中设置为 true。这意味着 Disposed 属性只有在调用基类 Dispose 时才能返回 true (当然,除非是邪恶的反射)。这允许基类提供可执行的合同。

现在考虑相反的情况,那里有一个受保护的二传手。现在,任何类都可以任意将 Disposed 属性设置为 true,而无需处理任何内容。这为 Dispose 创造了一个机会,可以在没有处理任何内容时返回 true。

我会选择第一个选项,因为它提供了最具可执行性的合同。

于 2009-07-03T15:46:18.803 回答
0

我建议在基类上使用公共 getter 和受保护的 setter 的 Disposed 属性。

于 2009-07-03T15:05:46.907 回答
0

如果您的方法在处理类时应该做一些不同的事情,例如抛出异常,我将为读取基类上的私有字段的基类创建一个仅受保护的 getter 属性。这样您就可以让任何继承者知道他是否能够执行操作。

然后,为了知道一个类是否已经被部署到它自己的 dispose 方法中(例如:避免两次释放资源),我认为拥有一个私有标志更好地清晰和维护。

于 2009-07-03T15:30:56.940 回答
0

除了 JaredPar 的回答之外,我还要补充一点,并不总是需要有一个_disposed标志。很多时候,对象的其他“资源相关”字段自然地提供了一种表示已处置状态的方法。

例如,Shutdown在丢弃之前需要存在的外部 COM 对象将由对 COM 对象的引用表示,因此相关部分Dispose将是:

if (_comObject != null)
{
    _comObject.Shutdown();
    _comObject = null;
}

这可以安全地运行多次,而无需根据需要多次调用Shutdown。之后尝试使用 _comObject 的其他方法Dispose将获得 a NullReferenceException,或者理想情况下,这些方法将检查 _comObject 字段并抛出ObjectDisposedException

我发现这往往是正确的——经常实现 IDisposable,我不记得曾经需要一个单独的_disposed字段。引入一个会增加自由度(增加我搞砸的方式)。

因此,即使这是一个安全的想法(它不是,正如 JaredPar 解释的那样),这对于派生类也不太可能有用。

于 2009-07-03T15:56:01.180 回答