5

私が取り組んでいるプロジェクトで、次のコードのようなものになりました。私はそれを許されたことは本当に奇妙だと思いましたが、今では、私の側の建築上の失敗が私をこれに導いた可能性が最も高いのだろうかと考え始めています.

あなたへの私の質問は次のとおりです。

  • これは正確には何と呼ばれていますか?
  • これは実際にどのような用途に使用されていますか?
  • なぜ誰もがこれをやりたいのですか?

ここに私のインターフェースがあります:

namespace ThisAndThat
{
    public interface ICanDoThis
    {
        string Do();
    }

    public interface ICanDoThat
    {
        string Do();
    }

    public interface ICanDoThisAndThat : ICanDoThis, ICanDoThat
    {
        new string Do();
    }
}

ここに私の具象クラスがあります:

namespace ThisAndThat
{
    public class CanDoThisAndThat : ICanDoThisAndThat
    {
        public string Do()
        {
            return "I Can Do This And That!";
        }

        string ICanDoThis.Do()
        {
            return "I Can Do This!";
        }

        string ICanDoThat.Do()
        {
            return "I Can Do That!";
        }
    }
}

そして私の合格テスト:

using Xunit;

namespace ThisAndThat.Tests
{
    public class ThisAndThatTests
    {
        [Fact]
        public void I_Can_Do_This_And_That()
        {
            ICanDoThisAndThat sut = new CanDoThisAndThat();

            Assert.Equal("I Can Do This And That!", sut.Do());
        }

        [Fact]
        public void I_Can_Do_This()
        {
            ICanDoThis sut = new CanDoThisAndThat();

            Assert.Equal("I Can Do This!", sut.Do());
        }

        [Fact]
        public void I_Can_Do_That()
        {
            ICanDoThat sut = new CanDoThisAndThat();

            Assert.Equal("I Can Do That!", sut.Do());
        }

    }
}
4

2 に答える 2

5

このコードには何の問題もありません (ユーザーを混乱させない限り)。また、私がよく知っている名前のパターンでもありません。 CanDoThisAndThatは 2 つのインターフェイスを実装しているため、クライアントはどちらの方法でも使用できます。

.NET では、明示的なインターフェイスの実装と呼ばれる方法でインターフェイスを実装できます。

明示的なインターフェイスの実装は、次の場合に役立ちます。

  1. 2 つのインターフェースが同じメンバー定義を持っている
  2. インターフェイスを実装する必要があるが、インターフェイス型を使用して参照を宣言していないクライアント コードで特定のメンバーが使用可能であることを公表したくない場合

.NET フレームワークのケース 2 の例は次のとおりですICollection.SyncLock。 BCL の設計者がこの方法でコレクションをロックすることを推奨しなくなったため、メンバーが意図的に「非表示」になっているため、次のコードはコンパイルされませんList<T>ICollection

List<object> list = new List<object>();

lock (list.SyncRoot) // compiler fails here
{
    // ...
}

ICollection参照は明示的に型であるため、この形式のレガシー コードは引き続き機能します。

ICollection list = new List<object>();

lock (list.SyncRoot) // no problem
{
    // ...
}
于 2009-02-13T07:21:45.647 に答える
4

各タイプにはインターフェイス マッピングがあります (リフレクションで確認したい場合は、 Type.GetInterfaceMapで取得できます)。これは基本的に、「インターフェイス Y のメソッド X が呼び出されると、このメソッド Z が呼び出される」ということです。C# ではサポートされていませんが、マッピング ターゲット メソッドがインターフェイス メソッド名とは異なる名前を持つ可能性があることに注意してください。(VB はこれを明示的にサポートしていると思います。)

あなたの場合、3 つのメソッドがあり、3 つのメソッドのそれぞれが、関連するインターフェイスの 1 つのメソッドに対応しています。

コンパイラがインターフェイスを介して仮想メソッドへの呼び出しを発行すると、生成された IL は「このオブジェクトで IFoo.Bar を呼び出す」のようなメッセージを表示し、IFoo.Bar はインターフェイス マップを使用して解決されます。

戻り値の型だけが異なる署名がある場合、または同じメソッド名を持つが異なることを行う必要がある 2 つの異種インターフェイスを実装している場合に、これを使用する必要がある場合があります。ただし、回避できるところはどこでも実行してください。非常に紛らわしいコードになります。

于 2009-02-13T07:13:17.603 に答える