具体类如何隐藏它实现的接口的成员

本文关键字:实现 隐藏 接口 成员 何隐藏 | 更新日期: 2023-09-27 17:52:16

我将给出一个来自。net的例子。

ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary

这里你可以看到ConcurrentDictionary实现字典接口。然而,我不能从ConcurrentDictionary实例访问Add<TKey,TValue>方法。这怎么可能呢?

IDictionary<int, int> dictionary = new ConcurrentDictionary<int, int>();
dictionary.Add(3, 3); //no errors
ConcurrentDictionary<int, int> concurrentDictionary = new ConcurrentDictionary<int, int>();
concurrentDictionary.Add(3, 3); //Cannot access private method here

更新:

我知道如何访问它,但我不知道显式实现接口可以允许将访问修饰符更改为internal。但它仍然不允许将其设为私有。这是正确的吗?对那部分进行更详细的解释会很有帮助。我还想知道一些有效的用例。

具体类如何隐藏它实现的接口的成员

因为IDictionary.Add方法是由ConcurrentDictionary显式实现的。

要从类中访问它,而不必将变量声明为字典,将其强制转换为所需的接口:

((IDictionary)concurrentDictionary).Add(3, 3)

这是通过显式接口实现的

public interface ISomeInterface
{
    void SomeMethod();
}
public class SomeClass : ISomeInterface
{
    void SomeInterface.SomeMethod()
    {
        // ...
    }
}

现在,当您有对SomeClass对象的引用时,您将看不到SomeMethod方法可用。为了调用它,你必须将对象强制转换回ISomeInterface

((ISomeInterface)mySomeClass).SomeMethod();

这是c#中尚未充分利用的有用特性之一。

它是作为显式接口实现的,这意味着您需要一个IDictionary<TKey, TValue>类型的变量来访问它。

参见ConcurrentDictionary<TKey, TValue>的文档,在显式接口实现部分。

如果你将并发字典强制转换为IDictionary<TKey, TValue>,你将能够调用Add


我不知道显式实现接口可以允许将访问修饰符更改为internal。但它仍然不允许将其设为私有。这是正确的吗?

不,这是不对的。

显式接口实现不改变访问修饰符。它们改变了你访问以这种方式实现的成员的方式(即要求你使用接口类型的变量)。它们仍然是公共成员,但只能使用接口类型访问,而不能使用实现类型。

显式接口实现。对于一个更简单的例子:

public interface IFoo {
    void Bar();
}
public class Foo : IFoo {
    void IFoo.Bar() { ... }
}

这里Bar不是Foo的公共API

接口显式实现。在下面的例子中,你不能使用一个类的实例来访问Add方法。

public interface IA
{
    void Add();
}
public class A : IA
{
    void IA.Add()
    {
        throw new NotImplementedException();
    }
}

访问修饰符未更改;ConcurrentDictionary<TKey, TValue>通过显式接口实现定义了IDictionary.Add方法,没有实现Add方法。

如果您查看类文档,您将看到没有Add方法存在(因此concurrentDictionary.Add(3, 3);将类似于调用concurrentDictionary.MethodThatDoesntExist(3, 3);)。然而,在显式接口实现部分,您可以看到有ICollection.AddIDictionary.Add方法。

这个特性允许一个类实现共享一个方法名的多个接口,而不要求每个接口的实现都是相同的。

感谢大家的精彩回答,其中一个被删除的答案让我对访问修饰符感到困惑。我从相关的问题中找到了一些很好的解释。

Michael Hopcroft的隐式和显式接口实现

Jon Skeet的一些用例

显式实现IDisposable

Brad Abrams的显式成员实现设计指南

令人讨厌的模糊重载,第一部分&第二部分/Eric Lippert