この記事によると、次のように書かれています。
次の状況でデリゲートを使用します。
- クラスには、メソッドの複数の実装が必要な場合があります。
次の状況でインターフェイスを使用します。
- クラスには、メソッドの実装が 1 つだけ必要です。
誰かが私にこれを説明できますか?
それは...奇妙で紛らわしいです。メソッドの実装が 1 つだけ必要な場合は、メソッド(おそらく仮想メソッド) を使用します。インターフェイスと同様に、デリゲートのポイントの 1 つは、複数の異なる実装を置き換えることができることです。
要約する必要がある場合:
デリゲート型は、単一のメソッドのみを公開するインターフェイスに非常によく似ており、デリゲート インスタンスは、そのインターフェイスを実装
x => 2 * x
するクラスのインスタンスに非常によく似ています。つまり、インスタンスを必要とせずに (場合によっては)書き込みます。
デリゲートには他にも役立つトリックevents
(マルチキャストなど) がありますが、それは記事の文脈とは関係ないように思えます。
クラスには、メソッドの複数の実装が必要な場合があります。
public delegate int PerformCalculation(int x, int y);
void SomeMethod()
{
PerformCalculation PerformCalculation_1 = myDelegateFun_1;
PerformCalculation PerformCalculation_2 = myDelegateFun_2;
PerformCalculation_1(5, 3);
PerformCalculation_2(5, 3);
}
private int myDelegateFun_1(int x, int y)
{
return x + y;
}
private int myDelegateFun_2(int x, int y)
{
return x + y;
}
上記の例では、PerformCalculation_1、PerformCalculation_2はPerformCalculationの複数の実装です
A class only needs one implementation of the method
interface IDimensions
{
float Length();
}
class Box : IDimensions
{
float Length()
{
return lengthInches;
}
}
上記の例では、インターフェースによって公開されるメソッドの単一の実装のみです。
私の単純な頭では、これは ICompare/IComparable とよく似ています。
インターフェイスの実装は、動作が実装クラスに固有であることを意味します。発信者や通話の状況によって動作が変わることはありません。
デリゲートは、操作がクラスに固有のものではなく、定義するコンテキストまたは呼び出し元に基づいていると言っています。
• インターフェイスは 1 つのメソッドのみを定義します。•マルチキャスト機能が必要です。• サブスクライバは、インターフェイスを複数回実装する必要があります。
この言い回しは少し混乱しているように見えますが、例を挙げて説明することができます。クリックされたときに通知を提供するボタン コントロールを設計しているとします。一般的な方法は、呼び出すデリゲートのリストをボタンで維持することです。ボタンがそれ自体のインスタンスでメソッドの 1 つを呼び出すようにしたい場合、クラスは、そのインスタンスでそのメソッドを呼び出すデリゲートを簡単に作成できます。この目的でデリゲートを使用すると、デリゲートが呼び出すメソッドを持つインスタンスに加えて、デリゲートのヒープ オブジェクトを構築する必要があることに注意してください。
別のアプローチはINotifyOfButtonClick
、メソッドを使用してインターフェイスを定義しNotifyOfButtonClick()
、ボタン コントロールに のリストを保持させることですINotifyButtonClick
。ボタンをクリックするとNotifyOfButtonClick()
、各インスタンスが呼び出されます。フォームにそのインターフェイスを使用するボタンが 1 つしかない場合、またはそのようなボタンがすべて同じメソッドを使用する場合、フォームはINotifyOfButtonClick()
それ自体を実装し、ボタンのサブスクリプション リストに追加することができます。別のデリゲートを作成する必要はありません。そのメソッドを呼び出します。このアプローチが機能するシナリオでは、デリゲートを使用するよりも効率的です。ただし、フォームに同じインターフェイスを使用する 2 つのボタンがあり、異なるメソッドを呼び出したい場合、事態はさらに複雑になります。その場合、実装を目的とする新しいオブジェクトをフォームで作成する必要があります。INotifyOfButtonClick()
参照を保持するフォームで何らかのメソッドを呼び出すことによって。このようなラッパー オブジェクトを使用すると、デリゲートに匹敵するパフォーマンスが得られる可能性がありますが、コンパイラの支援がなければ、デリゲートのようになります。
ところで、Microsoft がネストされたインターフェイスを各デリゲートに追加できる場合IInvoke
(たとえばAction<int>
、 interface を定義するなどAction<int>.IInvoke
)、 を受け入れるメソッドがAction<int>
を受け入れるように書き直された場合Action<int>.IInvoke
、そのようなデリゲートによって呼び出されるメソッドが 1 つしかないオブジェクト単純にそのようなメソッドに自分自身を渡すことができます。このような機能により、閉鎖の効率が向上する可能性があります。