如何隐藏一个dispose方法?

5
我是一名第三方API dll的用户,使用的是彭博SAPI。以下是我的问题:
[ComVisible(true)]
public interface IDisposable     
{ //this is from mscorlib 2.0.0.0 - standard System.IDisposable
    void Dispose();
}

public abstract class AbstractSession : IDisposable {}//method signatures and comments

public class Session : AbstractSession {} //method signatures and comments (from assembly metadata)

上述内容来自VS2010中的F12 /转到定义/对象浏览器。现在,当我尝试使用以下代码时:
(new Session()).Dispose();

这段代码无法编译...标准编译器错误-找不到定义/扩展方法'Dispose'。

这怎么可能?他们制作了一个程序集并明确编辑了它的元数据吗?

我不知道在法律上是否可以隐藏(排除)公共方法....

1个回答

18
这被称为显式接口实现。类的写法如下:
class Session : IDisposable {
    void IDisposable.Dispose() {
        // whatever
    }
}

只有当您的变量是类型为IDisposable时,才能调用它,如下:

IDisposable mySession = new Session();
mySession.Dispose();

通过转换:
((IDisposable)mySession).Dispose();

使用using语句,它在完成后自动调用Dispose(这仅适用于实现了此接口的任何对象进行处理的最佳实践):
using (var session = new Session()) { }

啊啊啊!太好了。我以前从未使用过显式实现,所以不知道需要接口转换才能使用它。谢谢! - Vivek
显式接口实现通常不是必需的,但有时很有用,比如当你想强制你的同事按照接口编码而不是实现时。还有一些情况下是必要的,比如当你需要实现两个具有相同成员签名的不同接口,而你需要以两种不同的方式实现它们时。 - Joe Enos
好的。谢谢。正如你所提到的,除非方法名冲突,否则很少需要使用显式 unless 方法,因此这是我第一次在生产代码中看到它。不知道 DISPOSE 和什么发生了冲突! :) - Vivek
1
@JoeEnos - 说得对。显式接口实现的一个常见情况是在实现 IEnumerable<T> 时;因为它派生自非泛型的 IEnumerable,所以你必须实现两个版本的 GetEnumerator,并且它们可能会互相干扰。因此,最佳实践是显式实现非泛型方法,这样只有在将集合视为非泛型时才调用它。 - KeithS
@KeithS 好主意,我试图想到一个有冲突的例子,这是一个好例子。就个人而言,除非有理由不这样做,否则我总是显式地声明。 - Joe Enos
1
@Vivek - 嗯,既然这个类已经注册了COM互操作,除了名称冲突之外还可能有其他原因。像Dispose()这样的主要处理.NET内存管理的方法,可能只对也在.NET沙盒中的消费者有价值;非托管代码将有其他方式来销毁引用,就像JVM等不同托管运行时中的代码一样。因此,通过要求您显式转换为IDisposable以调用Dispose,代码基本上迫使您证明自己处于.NET领域。 - KeithS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接