2017-08-16 5 views
3

は:すべてのインターフェイスを継承チェーンに含める必要がありますか?私は2つのインターフェイスがある場合

interface IGrandparent 
    { 
     void DoSomething(); 
    } 

    interface IParent : IGrandparent 
    { 
     void DoSomethingElse(); 
    } 

をその後、2つの実装があります。

//only includes last interface from the inheritance chain 
public class Child1 : IParent 
{ 
    public void DoSomething() 
    { 
     throw new NotImplementedException(); 
    } 

    public void DoSomethingElse() 
    { 
     throw new NotImplementedException(); 
    } 
} 

// includes all the interfaces from the inheritance chain  
public class Child2 : IGrandparent, IParent  
{ 
    public void DoSomething() 
    { 
     throw new NotImplementedException(); 
    } 

    public void DoSomethingElse() 
    { 
     throw new NotImplementedException(); 
    } 
} 

は、これらの2つの実装は同じではありますか? (クラス名を除く)?何人かは「暗黙的かつ明示的な実装」と関係があると言いますが、なぜその理由を説明するのでしょうか?私はChild2様式を他のものよりも多く見ました。

+1

「同一」は明確に定義されていません。 Err、それはよく定義されていて、そうではありません。しかし、すべての実用的な目的のために、 'interface IB:IA'の場合、' class B:IB 'と比較して 'class B:IB、IA'と書いても意味がありません。唯一の違いは、誰かが後に 'IA'から継承する' IB' *を*変更しなかった場合です。それは違いを生み出すでしょう。しかし、通常は設計時に心配することはありません。ちょうど 'IParent'を実装してください。 –

+1

Child2のスタイルがより頻繁に見られる場合は、どうして内部的にどうなるのかを確かめてください。私はそれの利点の多くを見ていないが、多分誰かが明らかにすることができます。明確化が意味をなさない場合は、ここに再度お尋ねください。しかし、例えばMSは明示的に宣言していない。一覧 ':IEnumerableを' https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs –

+0

それは文体の選択である、あなたは、あなたのチームのコーディング標準がそれを必要とするなら、「はず」。明示的な実装と明示的な実装は関係がありません。どちらのスタイルでも、インターフェースに共通のメンバー名がある場合は明示的に要求されます。コーディングの標準を一切使わずに作業していて、好みがない場合は、マイクロソフトのプログラマが行う方法、つまり2番目のスタイルを実行してください。 –

答えて

1

これらは同じです。

1が明示的に例えば、両方Child1Child2スタイルを使用して、インターフェイスを実装することができますので、これは、明示的なインターフェイスの実装に関するものではありません。これはインタフェース再実装と混同すべきではないことを

public class Child2 : IGrandparent, IParent 
{ 
    void IGrandparent.DoSomething() 
    { 
     throw new NotImplementedException(); 
    } 

    public void DoSomethingElse() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class Child1 : IParent 
{ 
    void IGrandparent.DoSomething() 
    { 
     throw new NotImplementedException(); 
    } 

    public void DoSomethingElse() 
    { 
     throw new NotImplementedException(); 
    } 
} 

注意、クラス階層内:

public class Child1 : IParent 
{ 
    public void DoSomething() 
    { 
     Console.WriteLine("Child1.DoSomething"); 
    } 

    public void DoSomethingElse() 
    { 
     Console.WriteLine("Child1.DoSomethingElse"); 
    } 
} 

public class Child2 : Child1, IGrandparent 
{ 
    // Child2 re-implements IGrandparent 
    // using explicit interface implementation 
    void IGrandparent.DoSomething() 
    { 
     Console.WriteLine("Child2.DoSomething"); 
    } 
} 

Child2のスタイルは避けてください。それは単に視覚的なごみです。 IGrandparentはあなたの責任ではない場合さらに、その後、いつかあなたはこれを取得します:

interface IGrandparent : ICthulhu { ... } 

あなたはこのようあなたコードを更新しますか:

public class Child2 : ICthulhu, IGrandparent, IParent { ... } 

+0

私はCHILD1スタイルを好むが、あまりにも多くのCHILD2スタイルは私が心配しますと、私はこの質問を持っている理由です。みんなありがとう。 –

4

明示的なインターフェイス実装は、異なるインターフェイスのメソッド名が競合しない場合に発生します。これは一般的なケースです。
これに対して、Excplicitは、メソッド名が競合している場合です。この時点で、メソッドに実装されているインターフェイスを指定する必要があります。

public interface IFoo 
{ 
    void Do(); // conflicting name 1 
} 

public interface IBar 
{ 
    void Do(); // conflicting name 2 
} 

public class FooBar : IFoo, IBar 
{ 
    void IFoo.Do() // explicit implementation 1 
    {    
    } 

    void IBar.Do() // explicit implementation 1 
    { 
    } 
} 

明示的に実装されたインターフェイスメソッドを公開することはできません。 Here you can read more about explicit interface implementation.

具体的な例について話す。安全に使用できるのはIParentです。明示的なインタフェースの実装を使用したいとしても、クラス宣言で具体的にIGrandparentを言及せずに行うことができます。

interface IGrandparent 
{ 
    void DoSomething(); 
} 

interface IParent : IGrandparent 
{ 
    void DoSomethingElse(); 

    void DoSomething(); 
} 

public class Child : IParent 
{ 
    void IGrandparent.DoSomething() 
    { 
    } 

    public void DoSomethingElse() 
    { 
    } 

    public void DoSomething() 
    { 
    } 
} 

EDIT:Dennisが指摘したように、インタフェース再実装を含む、明示的なインターフェイス実装の使用の他のいくつかの場合があります。私は、暗黙的対明示的なインターフェイスの実装の使用方法については、非常に良い理由があることを発見したhere(あなたは全体のスレッドをチェックアウトすることがあります、それは魅力的です)。

+0

「矛盾するメソッド名がある場合Excplicitは...です」。少なくとも、さらに2つのケースがあります。1)インターフェースの再実装。ベースクラスがインターフェイスメソッドを非仮想クラスにマップするとき。 2)一つだけいくつかの特別な状況(例えば、EF6で 'IObjectContextAdapter'を参照)で使用するために特定のインタフェースの実装を隠蔽したい場合。 – Dennis

+0

@Dennisありがとう、私は私の答えを更新しました! –