6

我将举一个 .NET 的例子。

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

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

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

更新:

我知道如何访问它,但我不知道显式实现接口可以允许将访问修饰符更改为内部。它仍然不允许将其设为私有。这个对吗?关于该部分的更详细的解释会有所帮助。另外我想知道一些有效的用例。

4

7 回答 7

7

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

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

((IDictionary)concurrentDictionary).Add(3, 3)
于 2013-01-11T14:32:15.310 回答
5

这是通过显式接口实现来完成的

public interface ISomeInterface
{
    void SomeMethod();
}

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

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

((ISomeInterface)mySomeClass).SomeMethod();

这是 C# imo 中未被充分利用的有用特性之一

于 2013-01-11T14:32:02.600 回答
4

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

ConcurrentDictionary<TKey, TValue>请参阅Explicit Interface Implementations 部分下的文档。

如果您将并发字典转换为IDictionary<TKey, TValue>,您将能够调用Add它。


我不知道显式实现接口可以允许将访问修饰符更改为内部。它仍然不允许将其设为私有。这个对吗?

不,这是不正确的。

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

于 2013-01-11T14:32:24.313 回答
2

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

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

这里Bar不在Foo.

于 2013-01-11T14:32:46.637 回答
2

该接口是显式实现的。在以下示例中,您无法Add使用 A 类的实例访问方法。

public interface IA
{
    void Add();
}

public class A : IA
{
    void IA.Add()
    {
        throw new NotImplementedException();
    }
}
于 2013-01-11T14:37:11.027 回答
0

感谢大家提供出色的答案,其中一个已删除的答案让我对访问修饰符感到困惑。我能够从链接的问题中找到一些很好的解释。

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

Jon Skeet 的一些用例

显式实现 IDisposable

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

可恶的模棱两可的重载,第一部分第二部分Eric Lippert

于 2013-01-11T15:22:21.177 回答
0

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

如果您查看类文档,您会发现不Add存在任何方法(因此concurrentDictionary.Add(3, 3);类似于调用concurrentDictionary.MethodThatDoesntExist(3, 3);)。但是,在Explicit Interface Implementations 部分下,您可以看到有方法ICollection.AddIDictionary.Add

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

于 2013-01-11T15:00:12.100 回答