【问题标题】:How can a concrete class hide a member of the interface that it implements具体类如何隐藏它实现的接口的成员
【发布时间】:2013-01-11 14:30:33
【问题描述】:

我将举一个来自 .NET 的示例。

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

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

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

更新:

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

【问题讨论】:

  • 显式接口实现不会更改访问修饰符。它们改变了如何您可以访问以这种方式实现的成员(即要求您使用接口类型的变量)。
  • 查看stackoverflow.com/questions/6129857/…了解一些cmets的使用情况
  • 类中的默认可见性级别是private,与java中的package相反。显式接口实现是私有的,所以不,您的假设不正确。

标签: c# .net


【解决方案1】:

因为IDictionary.Add 方法是explicitly implemented by ConcurrentDictionary。

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

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

【讨论】:

    【解决方案2】:

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

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

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

    ((ISomeInterface)mySomeClass).SomeMethod();
    

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

    【讨论】:

      【解决方案3】:

      它被实现为explicit interface implementation,这意味着您需要一个IDictionary&lt;TKey, TValue&gt; 类型的变量来访问它。

      请参阅ConcurrentDictionary&lt;TKey, TValue&gt; 的文档,位于显式接口实现部分下。

      如果您将并发字典转换为IDictionary&lt;TKey, TValue&gt;,您将能够在其上调用Add


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

      不,这是不正确的。

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

      【讨论】:

        【解决方案4】:

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

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

        这里Bar 不在Foo 的公共API 上。

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

            【解决方案6】:

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

            如果您查看class documentation,您会发现不存在Add 方法(因此concurrentDictionary.Add(3, 3); 类似于调用concurrentDictionary.MethodThatDoesntExist(3, 3);)。不过在Explicit Interface Implementations section下,可以看到有ICollection.AddIDictionary.Add这两个方法。

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

            【讨论】:

              【解决方案7】:

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

              Implicit and Explicit Interface Implementations迈克尔·霍普克罗夫特

              Some use cases by Jon Skeet

              Implementing IDisposable explicitly

              Design Guidelines for Explicit Member Implementation 布拉德·艾布拉姆斯

              Odious ambiguous overloads, part one & part two 埃里克·利珀特

              【讨论】:

                猜你喜欢
                • 2016-10-30
                • 1970-01-01
                • 1970-01-01
                • 2011-07-14
                • 2014-01-26
                • 1970-01-01
                • 2023-02-15
                • 1970-01-01
                • 2010-11-16
                相关资源
                最近更新 更多