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