デリゲートとイベントの識別

前へ

.NET Core プラットフォームを初めて利用する開発者は、delegates に基づく設計と events に基づく設計のどちらにするか迷うことがあります。 デリゲートまたはイベントの選択は難しいことがよくあります。この 2 つの言語機能は非常に似ているためです。 さらに言えば、イベントはデリゲートの言語サポートを利用して構築されています。

いずれも遅延バインディングのシナリオを提供します。実行時にのみ認識されるメソッドを呼び出すことでコンポーネントが通信するシナリオが可能になります。 いずれもシングルとマルチのサブスクライバー メソッドに対応しています。 これはシングルキャストまたはマルチキャスト サポートと呼ばれることがあります。 いずれも、ハンドラーの追加と削除に同じような構文を利用しています。 最後になりますが、イベントを発生させ、デリゲートを呼び出すとき、まったく同じメソッド呼び出し構文が使用されます。 いずれも、?. 演算子で使用する同じ Invoke() メソッド構文をサポートしています。

このような類似点があるため、どちらを使用するか決定することは簡単ではありません。

イベントの待機は任意です

使用する言語機能を決定するときに考慮するべき最も重要なことは、サブスクライバーをアタッチする必要があるのかどうかです。 サブスクライバーが提供するコードをコードで呼び出す必要がある場合、コールバックを実装する必要があるとき、デリゲートに基づくデザインを使用してください。 サブスクライバーを呼び出さなくてもすべての作業をコードで完了できる場合、イベントに基づくデザインを使用してください。

このセクションで作成されたサンプルを考察してください。 List.Sort() を利用して作成したコードには、要素を適切に並べ替える目的で、比較関数を与える必要があります。 LINQ クエリには、返す要素を決定する目的で、デリゲートを指定する必要があります。 いずれもデリゲートで作成したデザインを使用しています。

Progress イベントを考察してください。 これはタスクの進行状況を報告します。 リスナーの有無に関係なく、このタスクは続行します。 FileSearcher は別の例です。 イベント サブスクライバーがアタッチされていませんが、要求されたすべてのファイルを検索します。 サブスクライバーがイベントを待ち受けていなくても、UX コントロールは正しく動作します。 いずれもイベントに基づくデザインを使用しています。

戻り値でデリゲートが必要になる

別の考慮事項として、デリゲート メソッドのために必要なメソッド プロトタイプがあります。 ご覧のとおり、イベントに使用されるデリゲートにはすべて戻り値の型 void が与えられます。 また、イベント引数オブジェクトのプロパティを変更することでイベント ソースに情報を戻すイベント ハンドラーを作成する表現形式があります。 そのような表現形式は実際に機能しますが、メソッドから値を返すことと同じように自然ではありません。

この 2 つのヒューリスティックは両方とも存在する可能性があります。デリゲート メソッドが値を返す場合は、何らかの形でアルゴリズムに影響を与える可能性があります。

イベントにプライベート呼び出しがある

イベントが含まれているもの以外のクラスは、イベント リスナーの追加と削除のみを実行できます。イベントを呼び出すことができるのは、イベントを含むクラスだけです。 イベントは、一般にパブリック クラスのメンバーです。 これに対して、デリゲートが格納されるのであれば、これはパラメーターとして渡され、プライベート クラスのメンバーとして格納されることが多いです。

イベント リスナーの有効期間が頻繁に長くなる

イベント リスナーの有効期間が長くなることは、少々弱い根拠です。 しかしながら、イベント ソースが長期間にわたりイベントを発生させるとき、イベント基準の設計の方が自然であることがあります。 UX コントロールのイベント基準の設計の例は、多くのシステムで確認できます。 イベントを受信登録すると、イベント ソースはプログラムの有効期間にわたりイベントを発生させることがあります。 (不要になったらイベントの受信登録を解除できます。)

さまざまなデリゲート基準デザインと比較してみてください。デリゲート基準デザインの場合、デリゲートはメソッドの引数として使用され、そのメソッドが戻った後、デリゲートは使用されません。

慎重に評価する

以上の考慮事項は絶対厳守の決まりではありません。 代わりに、特定の用途に最適な選択肢はどれかを決定する際の指南になります。 どちらも似ているため、両方を試作し、どちらが自然に動作するか検討するという方法もあります。 いずれも遅延バインディング シナリオを効率的に処理します。 自分の設計を最もよく伝える方を利用してください。