web-dev-qa-db-ja.com

明示的なインターフェースの実装がそのように機能するのはなぜですか?

このプログラムが「ベース名」の代わりに「子名」を印刷するのはなぜですか?

using System;

class Program
{
    static void Main(string[] args)
    {
        var child = new Child();
        Console.WriteLine(((INamedObject)child).Name);
        Console.ReadLine();
    }
}

interface INamedObject
{
    string Name { get; }
}

class Base : INamedObject
{
    string INamedObject.Name
    {
       get
       {
         return "Base Name";
       }
    }
}

class Child : Base, INamedObject
{
   public string Name
   {
      get
      {
         return "Child Name";
      }
   }
}

childINamedObjectにキャストすると、INamedObjectのNameプロパティが明示的に実装されると思います。しかし、どうなるかというと、Child.Nameプロパティが呼び出されます。

なぜChildのようなクラスを宣言するのですか(INamedObjectChildから削除):

class Child : Base
{
   public string Name
   {
      get
      {
         return "Child Name";
      }
   }
}

「ベース名」の印刷を開始しますか?

8
ekalchev

他の答えは、あなたが偶然見つけたC#機能を正しく識別しません。

「インターフェースの再実装」と呼ばれるC#のやや紛らわしい機能を発見しました。ルールは、派生クラスが、基本クラスによって既に実装されているインターフェイスを具体的に再宣言する場合、コンパイラ最初からやり直して、インターフェイスマッピングを最初からやり直します

その場合、より多くの派生型のメソッドが、より少ない派生型のメソッドよりも優先されます、より派生型を開発している開発者は、基本クラスバージョンを開発した開発者よりもbetter実装。結局のところ、派生バージョンがworseであった場合、開発者はそれを実装しなかったでしょう。

このルールを使用すると、派生クラスで基本クラスインターフェイスマッピングを置き換えるかどうかを決定できます。必要な場合とそうでない場合があるためです。

詳細については、この機能に関する私の2011年の記事を参照してください。

https://blogs.msdn.Microsoft.com/ericlippert/2011/12/08/so-many-interfaces-part-two/

この回答も役に立ちます:

インターフェースを実装する抽象基本クラス

この言語機能を説明する仕様のセクションについては、

https://docs.Microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/interfaces#interface-re-implementation

12
Eric Lippert