【问题标题】:Unusual member override syntax in C#C# 中不寻常的成员覆盖语法
【发布时间】:2011-06-28 21:52:39
【问题描述】:

所以,有人告诉我,解决类继承中的歧义的一个好方法是使用以下成语:

class INewList<T> : IList, IList<T>
{
   new T IList<T>.this[int index] { get; set; }
}

我不太了解List&lt;T&gt;.this 语法。这与简单地做有什么不同:

new T this[int index] { get; set; }

这两个在功能上是否不同?在前面的示例中,我是否需要稍后提供索引器的实现,或者这段代码只是告诉编译器“嘿,在有疑问时使用IList&lt;T&gt; 中的索引器实现”?

【问题讨论】:

    标签: c# syntax indexer


    【解决方案1】:

    这就是explicit implementation。当您显式实现接口成员时,只能通过该类型(或子类型,见下文)的引用来调用它,因此换句话说,IList(非泛型)引用将无法调用你有的第一个例子。

    以下是子类型事物如何工作的示例:

    void Main() {
        I2 myC = new C();
        myC.Operation();
    }
    
    interface I1 {
        void Operation();
    }
    
    interface I2 : I1 {  }
    
    class C : I2 {
        void I1.Operation() {
            Console.WriteLine ("called operation");
        }
    }
    

    如果执行此操作,您将看到控制台输出。如果myC 被声明为C,它将不起作用。

    (已更新以添加示例)

    【讨论】:

    • 通过“通过该类型的引用调用”,您究竟是什么意思?如果我的类型是INewList,从技术上讲,它是两种类型。如果我将它转换为IList&lt;T&gt;,你是说如果我尝试调用索引器它应该无法编译?那样的话,不就是用IList&lt;T&gt;的索引器吗?
    • 是的,这正是我所需要的。由于您添加了示例,因此我将您的示例标记为答案 :) 谢谢!
    【解决方案2】:

    这是对 this 的引用,作为 IList&lt;T&gt; 的实现者。
    否则,您无法从此属性返回 T,因为“普通”ILIst 的实现会产生歧义

    【讨论】:

      【解决方案3】:

      它显式地实现了一个接口的索引器。

      • 显式实现导致Interface.XYZ 语法
      • 索引器的名称是this,所以它变成Interface.this

      【讨论】:

        【解决方案4】:

        它被称为explicit interface implementation,它用于解决诸如实现两个碰巧共享一个成员名称的接口之类的问题。 基本上,它是一个只能在对象被转换到特定接口时调用的方法。

        说:

        INewList<int> myList = new NewList<int>();
        myList[1] = 2;   // Error, this[int index] is not implemented.
        IList<int> myList2 = myList; // Cast as IList<int>
        myList2[1] = 2;  // Succeeds, it'll call IList<T>.this[int index].
        IList myList3 = myList; // Cast as IList
        myList3[1] = 2;  // Error, neither this[int index] nor IList.this[int index] are not implemented.
        

        当然,如果您实现了其中任何一个,它会调用相应的方法,显式实现会覆盖任何隐式实现。

        【讨论】:

        • 那么编译器产生这个错误的具体过程是什么?换句话说,我假设由于INewList 的索引器是多态的,无论您调用IList&lt;T&gt; 还是IList 的索引器,它都会检查具体类型的覆盖,如果它是显式的,则不要允许通话吗?
        • 老实说,我不知道它是如何工作的细节。不过,我想这是一个合理的猜测。另一种可能性是编译器专门寻找隐式实现或相应的显式实现,如果两者都找不到则抛出错误。
        【解决方案5】:

        您的代码示例非常混乱,无法编译。但是,要回答您关于 List&lt;T&gt;.this 语法的问题:

        这称为显式接口实现。您可以使用它来实现接口,但将其隐藏在类的公共签名中。这是一个小例子:

        public class Foo : IDisposable {
          public void Dispose() {
          }
        }
        
        public class Bar : IDisposable {
          public void Close() {
          }
          void IDisposable.Dispose() {
            Close();
          }
        }
        

        这两个类都实现了IDisposable,但要处理Bar,您必须调用Close。您也可以将其转换为IDisposable,然后调用Dispose

        var foo = new Foo();
        foo.Dispose();
        
        var bar = new Bar();
        bar.Close();
        ((IDisposable) bar).Dispose();
        

        对于FooBar 类,如果调用清理方法DisposeClose 可能并不重要,但对于File 类,您可能更喜欢Close 而不是Dispose它。其他用途是隐藏您必须实现的接口以参与对象之间的交互,但您不希望对类的消费者可见。或者,您可以使用它来解决使用冲突方法实现多个接口的问题。

        您可以在 MSDN 上阅读有关 explicit interface implementation 的信息。

        【讨论】:

          猜你喜欢
          • 2015-02-14
          • 1970-01-01
          • 2018-04-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-10
          • 1970-01-01
          相关资源
          最近更新 更多