【问题标题】:Explicit implementation of IDisposableIDisposable 的显式实现
【发布时间】:2011-07-31 10:33:13
【问题描述】:

虽然在 SO 上有很多关于 IDisposable 的问答,但我还没有找到答案:

我通常遵循这样的做法,即当我的一个类拥有IDisposable 对象时,它也会实现IDisposable 并在拥有的对象上调用Dispose。然而最近我遇到了一个明确实现IDisposable 的类,从而阻止我直接调用Dispose 迫使我强制转换它,我觉得这很烦人且不必要。

所以问题是:为什么以及何时需要使用IDisposable 的显式接口实现?我知道明确地实现一个接口有完全好的和正当的理由,但是关于IDisposable,我不太清楚原因。

【问题讨论】:

  • 这些“好的和正当的理由”是什么,为什么他们不应该为IDisposable 保留?为什么将对象投射到IDisposable 会“烦人”?
  • 有时一个类需要实现两个或多个成员名称会冲突的接口。这是显式接口命名的一个很好和正确的用途。我同意 OP 的观点,即任意命名清理方法而不是 Dispose 的约定是愚蠢的。即使一个类有一个 Close 方法,这并不意味着它不应该也有一个 Dispose 方法。由于在调用 Close 之后调用 Dispose 最坏的情况是有点多余,所以同时使用这两种方法有什么问题?
  • @chiccodoro:IMO 显式接口实现在需要实现两个具有冲突成员的接口时非常有用。在任何其他情况下,拥有可以转换为接口而不是“成为”接口的对象是不自然和烦人的。
  • @chiccodoro:我认为这个 SO 问题很好地涵盖了它:stackoverflow.com/questions/143405/…
  • @supercat:您对 Close 等的观点并没有真正理解。我说“为什么这些原因不应该同样适用于 IDisposable?” - 意思是:如果对象实现的接口恰好有“Dispose”方法,但与 IDisposable 不同,那么需要显式实现,不是吗?

标签: c# .net idisposable explicit-interface


【解决方案1】:

恕我直言,一个类显式实现 IDisposable 只有一个正当理由,那就是如果预计没有人真正需要调用它。一个类显式实现 IDisposable 这一事实可以被视为一个指标,表明人们可以安全地创建一个该特定类的对象,尽管不一定是派生类的对象,并且在创建时简单地放弃它。完成它。特定类缺少直接可用的 Dispose 方法可以被视为不需要对已知属于该特定类的对象调用 Dispose 的指示。

请注意,拥有和使用对实现 IDisposable 的对象的引用,而没有意识到它确实存在,这不是问题;然而,获得这样一个对象的所有权是。一个工厂方法的返回类型与 IDisposable.Dispose 没有任何关系并显式地实现它,但有时会返回一个期望正确 Disposal 的对象,这将是泄漏的秘诀。如果一个类可以用作此类工厂方法的返回类型,则该类不应显式实现 IDisposable。

就个人而言,我倾向于 Dispose 所有实现 IDisposable 的对象,无论它们是否需要。尽管如此,知道某些特定类型的 IDisposable 对象在确保正确处置否则会很困难或尴尬的情况下可能非常有用。

【讨论】:

    【解决方案2】:

    我会说这是一个很好的做法,它强制(除非你想强制转换为 IDisposable!!)使用 using

    using (ClassWithIDisposable) {
    }
    

    即使发生异常也会调用 Dispose

    此外,当使用 Castle 和 unity 等 IOC 框架时,您最终必须将 IDisposable 继承到您的接口,以便可以调用它。这些框架允许 AOP,因此您没有对实体类的引用,只有一个接口......

    【讨论】:

    • using 语句不适合问题中描述的场景 - 拥有 IDisposable 对象的类。
    • 它并没有真正强制使用using。没有人能阻止你做这样的事情var o = new MyDisposable(); o.DoSomething(); return;
    • 真的!也没有公开...我的意思是不要显式调用 .Dispose()
    • 当然,但正如 Joe 所说,在我的例子中,我在构造函数中实例化了对象,并希望在 Dispose 方法中处理它 - 所以使用不是一种选择。
    • Dispose 方法隐藏在显式接口实现之后意味着开发人员甚至可能没有意识到该类实现了IDisposable。不是一个好主意:如果您的班级需要被处置,那么您应该尽可能清楚地宣传该信息。
    【解决方案3】:

    我会说,除非您有替代的等效方法(例如关闭),否则明确实现 IDisposable.Dispose 是不寻常的。

    在这种情况下,您的包装类可以调用 Close 而不是强制转换。

    例如,Framework WebResponse 类。有趣的是,.NET 4 中有一个公共的 Dispose 方法,所以微软现在可能已经决定显式实现可能不是好的做法。

    CLR 安全团队的设计工程师 Shawn Farkas 在MSDN magazine 中写道

    虽然 using 块可以与具有显式 IDisposable 实现的类一起使用,但我建议类永远不要以这种方式实现接口。如果显式实现 IDisposable,在 Visual Studio® 中使用 IntelliSense® 探索对象模型的开发人员将不会注意到对象具有 Dispose 方法

    【讨论】:

    • 确实,我想要包装的类暴露了我最终使用的Close 方法。只是提供的示例代码明确包含:using (SomeClass o = new SomeClass()),因此很明显鼓励使用一次性模式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多