代码之家  ›  专栏  ›  技术社区  ›  morechilli

在IDisposable模式中,基类是否应允许派生类共享其已释放的标志?

  •  5
  • morechilli  · 技术社区  · 15 年前

    我目前正在修复一个C代码库,它没有一个良好的释放使用模式。

    它是一个大的代码库,它是一个资源要求很高的代码库,它使用许多自定义的非托管C++库。

    我对处理模式有很好的了解。我花了一些时间了解了我认为是关于这个问题的黄金标准条款: Joe Duffy's dispose article

    为了尽量减少代码重复,我们考虑了一些DisposeHelper类,因此我的问题是:

    如果一个基类实现了一个标准的Dispose模式,它应该允许共享其Disposed标志,即标记为Protected吗?

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

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

    4 回复  |  直到 10 年前
        1
  •  5
  •   Ian Nelson    10 年前

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

    例如,考虑在最基本类上具有只读释放属性的场景。仅在基类的Dispose(Disposing)方法中将backing字段设置为true。这意味着,只有在调用基类Dispose时,被释放的属性才能返回true(当然,除了邪恶的反射)。这允许基类提供一个可执行的契约。

    现在考虑下相反的情况,这里有一个受保护的setter。任何类现在都可以在不处理任何内容的情况下任意地将已处理的属性设置为true。这为Dispose创造了一个机会,使其在未处理任何内容时返回true。

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

        2
  •  0
  •   SLaks    15 年前

    我建议在具有公共getter和受保护的setter的基类上拥有已释放的属性。

        3
  •  0
  •   jmservera    15 年前

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

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

        4
  •  0
  •   Daniel Earwicker    15 年前

    除了Jaredpar的回答之外,我还要补充一点,并不总是有必要 _disposed 旗帜。通常,对象的其他“资源相关”字段自然提供了一种表示已处理状态的方法。

    例如,需要 Shutdown 在它被丢弃之前,将由对COM对象的引用来表示,因此 Dispose 将是:

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

    这可以安全地运行多次,而无需调用 关机 根据需要,不止一次。其他尝试在 处置 将得到一个 NullReferenceException 或者理想情况下,这些方法将检查对象字段并抛出 ObjectDisposedException .

    我发现这比不经常实现IDisposable更常见,我想不起来需要单独的 处置的 字段。引入一个会增加自由度(增加我把它搞砸的方法的数量)。

    所以这对于派生类来说不太可能有用,即使它是一个安全的想法(正如Jaredpar解释的那样,它不是)。

    推荐文章