私は現在、代表者の使用と目的を掘り下げようとしている限り、この質問を提起したいと思いますが、同様の定式化で尋ねられた可能性があります。
デリゲートは、C++で使用される関数ポインターとして機能することを知っています。事実は、C#でインターフェイスとポリモーフィズムの代替として主に機能するかどうかです。特定のクラスのサブクラスを作成し、各サブクラスに適切なメソッドを提供できるため、デリゲートを追加で提供するものは何ですか?それらの使用を規定するケースはありますか、またはデリゲートが使用されたときにコードの保守性が改善されるだけですか?インターフェイス上での幅広い展開をお勧めしますか?
私は代表者についてのみ話しているので、彼らの役割をイベントの役割と区別したいと思います。
はい、デリゲートは多くの点で単一メソッドインターフェイスに似ています。しかしながら:
最後のポイントは最も重要なポイントです-次のLINQ式を検討してください。
var query = collection.Where(x => x > 5)
.Select(x => x * x);
x > 5
とx * x
のロジックを表現する場合、式ごとに個別のクラスを作成し、インターフェースを実装する必要があると想像してください。もちろん、言語couldは、ラムダ式から別のクラスを介したインターフェイス実装への変換を可能にするように設計されていますが、別のメソッドを作成して、それをターゲットとして委任します。また、マルチキャスト機能も失われます。
同様の思考運動として、while
やfor
などのループステートメントを検討してください。 goto
が得られたら、本当に必要それらですか?いや。しかし、人生ははるかに優れていますwithそれら。同じことはデリゲートにも当てはまります。実際、プロパティ、イベントなどです。これらはすべて開発を簡単にします。
最大の実用的の違いは、同じクラスの同じデリゲートに異なるデリゲートインスタンスを提供できることですが、インターフェイスではできません。
void delegate XYZ(int p);
interface IXyz {
void doit(int p);
}
class One {
// All four methods below can be used to implement the XYZ delegate
void XYZ1(int p) {...}
void XYZ2(int p) {...}
void XYZ3(int p) {...}
void XYZ4(int p) {...}
}
class Two : IXyz {
public void doit(int p) {
// Only this method could be used to call an implementation through an interface
}
}
差出人 インターフェイス(MSDN)の代わりにデリゲートを使用する場合 :
デリゲートとインターフェイスの両方により、クラス設計者は型宣言と実装を分離できます。特定のインターフェイスは、任意のクラスまたは構造体によって継承および実装できます。メソッドがデリゲートのメソッドシグネチャに適合する限り、任意のクラスのメソッドに対してデリゲートを作成できます。インターフェイス参照またはデリゲートは、インターフェイスまたはデリゲートメソッドを実装するクラスの知識を持たないオブジェクトで使用できます。これらの類似性を考えると、クラスデザイナはいつデリゲートを使用する必要があり、いつインターフェイスを使用する必要がありますか?
次の状況でデリゲートを使用します。
- イベントデザインパターンが使用されます。
- 静的メソッドをカプセル化することが望ましいです。
- 呼び出し元は、メソッドを実装するオブジェクトの他のプロパティ、メソッド、またはインターフェイスにアクセスする必要はありません。
- 簡単な構成が望まれます。
- クラスには、メソッドの複数の実装が必要な場合があります。
次の状況でインターフェースを使用します。
- 呼び出される可能性のある関連メソッドのグループがあります。
- クラスには、メソッドの実装が1つだけ必要です。
- インターフェイスを使用するクラスは、そのインターフェイスを他のインターフェイスまたはクラスタイプにキャストします。
- 実装されるメソッドは、クラスのタイプまたはIDにリンクされます(たとえば、比較メソッド)。
デリゲートの代わりに単一メソッドインターフェイスを使用する1つの良い例は、
IComparable
または汎用バージョンIComparable
(Of T)です。IComparable
はCompareToメソッドを宣言します。CompareToメソッドは、同じ型の2つのオブジェクト間のより小さい、等しい、またはより大きい関係を指定する整数を返します。IComparable
は、ソートアルゴリズムの基礎として使用できます。ソートアルゴリズムの基礎としてデリゲート比較メソッドを使用することは有効ですが、理想的ではありません。比較する機能はクラスに属し、比較アルゴリズムは実行時に変更されないため、単一メソッドのインターフェイスが理想的です。
From C#のデリゲートとインターフェイス :
デリゲートとインターフェイスは、C#の2つの異なる概念ですが、共通点があります。デリゲートとインターフェイスの両方に宣言のみが含まれます。実装は、異なるプログラミングオブジェクトによって行われます。
デリゲートとインターフェイスは、C#の2つの異なる概念です。
インターフェイスは、オブジェクトの機能を拡張することができます。インターフェイスとそれを実装するオブジェクト間のコントラクトです。デリゲートは単なる安全なコールバックであり、一種の関数ポインタです。
インターフェイスに対するデリゲートの唯一の本当の利点は
.netがジェネリックをサポートしていなかった場合、デリゲートは必須の部分でした。なぜなら、渡すすべての異なる関数シグネチャに対して個別の非ジェネリックインターフェイスを宣言することは実行不可能だったからです。 .netが最初からジェネリックをサポートしていた場合、Reflectionを含む特定のシナリオを除いてデリゲートは不要でしたが、タイプAction<T,U>
をIAction<T,U>
の実装にすることはおそらく最も有用でした(そのため、単に必要なコードInvoke
がインターフェイスを使用できるもの)。インターフェイスベースのアプローチでは、クラスが複数のメソッドを公開するデリゲートを作成する必要がある場合は単一メソッドクラスを作成する必要がありましたが、メソッドの数が公開する署名は正確に1つです。
ちなみに、デリゲートをインターフェイスに置き換えても、汎用のCombineメソッドの作成が妨げられることはありません。実際、インターフェイスの共分散により、このようなメソッドは、多くの点で既存のDelegate.Combine
よりも機能しやすくなります。 Delegate.Remove
に類似したメソッドを実装するのはせいぜい面倒で迷惑ですが、Delegate.Remove
の使用を必要とするイベントサブスクリプション管理以外の状況は考えられません。