ほとんどの場合、明示的なインターフェイスの実装を使用します。主な理由は次のとおりです。
リファクタリングはより安全です
インターフェイスを変更するときは、コンパイラがそれをチェックできるとよいでしょう。これは、暗黙的な実装ではより困難です。
次の 2 つの一般的なケースが思い浮かびます。
このインターフェースを実装する既存のクラスが、たまたま新しいものと同じシグネチャを持つメソッドをすでに持っている場合に、インターフェースに関数を追加する。これにより、予期しない動作が発生する可能性があり、私は何度か苦しめられました。その関数はファイル内の他のインターフェイス メソッドと一緒に配置されていない可能性が高いため、デバッグ時に "確認" するのは困難です (後述の自己文書化の問題)。
インターフェイスから関数を削除します。暗黙的に実装されたメソッドは突然デッド コードになりますが、明示的に実装されたメソッドはコンパイル エラーによってキャッチされます。デッドコードは手元に置いておくのが良いとしても、強制的に見直して宣伝したい。
残念なことに、C# には、メソッドを暗黙的な実装としてマークするよう強制するキーワードがないため、コンパイラが追加のチェックを行うことができます。仮想メソッドには、'override' と 'new' を使用する必要があるため、上記の問題のいずれもありません。
注: 固定またはめったに変更されないインターフェイス (通常はベンダー API から) の場合、これは問題ではありません。ただし、私自身のインターフェースについては、いつどのように変更されるかを予測できません。
自己記録です
クラスに 'public bool Execute()' が表示された場合、それがインターフェイスの一部であることを確認するには、余分な作業が必要になります。誰かがおそらくそう言ってコメントするか、他のインターフェース実装のグループに入れなければならないでしょう。すべてリージョンまたはグループ化コメントの下に「ITask の実装」と書かれています。もちろん、これはグループ ヘッダーが画面外にない場合にのみ機能します。
一方、「bool ITask.Execute()」は明確で明確です。
インターフェイス実装の明確な分離
インターフェイスは、具体的な型の表面領域を少しだけ公開するように作成されているため、パブリック メソッドよりも「パブリック」であると考えています。それらは、タイプを機能、振る舞い、特性のセットなどに減らします。実装では、この分離を維持することが役立つと思います。
クラスのコードを調べているときに、明示的なインターフェイスの実装に出くわすと、私の脳は「コード コントラクト」モードに移行します。多くの場合、これらの実装は単純に他のメソッドに転送されますが、追加の状態/パラメーター チェック、内部要件により適合するための受信パラメーターの変換、またはバージョン管理の目的での変換 (つまり、複数世代のインターフェイスがすべて共通の実装に移行する) を行うこともあります。
(パブリックもコード コントラクトであることは認識していますが、特に具体的な型を直接使用することが通常内部専用コードの兆候であるインターフェイス駆動型のコードベースでは、インターフェイスの方がはるかに強力です。)
関連:Jonによる上記の理由2。
等々
さらに、ここの他の回答ですでに述べた利点:
問題
楽しいこと、幸せなことばかりではありません。私が暗黙に固執するいくつかのケースがあります:
- 値の型。これには、ボクシングとより低いパフォーマンスが必要になるためです。これは厳密な規則ではなく、インターフェイスとその使用目的によって異なります。匹敵する?暗黙。フォーマット可能? おそらく明示的です。
- 頻繁に直接呼び出されるメソッド (IDisposable.Dispose など) を持つ単純なシステム インターフェイス。
また、実際に具象型があり、明示的なインターフェイス メソッドを呼び出したい場合、キャストを行うのは面倒な場合があります。私はこれを次の 2 つの方法のいずれかで処理します。
- パブリックを追加し、実装のためにインターフェイス メソッドをそれらに転送します。通常、内部で作業する場合、より単純なインターフェイスで発生します。
- (私の好みの方法) a
public IMyInterface I { get { return this; } }
(インライン化する必要があります) を追加し、 を呼び出しますfoo.I.InterfaceMethod()
。この機能を必要とする複数のインターフェイスがある場合は、名前を I 以外に拡張します (私の経験では、この機能が必要になることはめったにありません)。