web-dev-qa-db-ja.com

イベントの登録にplus equals + =を使用するのはなぜですか?

C#では、次のようなイベントを登録します。

_window.onClick += myHandler;
_

しかし、ハンドラを取得して登録する「登録」メソッドの代わりにこれを使用する理由。例えば。:

_window.registerOnClick(myHandler);
_

_+=_は、少なくとも次の2つの理由で直観に反します。

  1. 誰かが_=_を使用して過去の登録を削除することはできませんか?しかし、より一般的には:
  2. 私のOOPクラスでは、常にパブリックメンバーではなくゲッターとセッターを使用するように言われました。

これは、Pythonでイベントを記述していて、最初に考えたのは、パブリックメンバー変数ではなくregister_handler_on_click(handler)を使用することでした。

7
jtpereyda

次のようなものを書こうとした場合:

window.onClick = myHandler;

+=または-=の右側でのみ許可されているイベントハンドラーに関するコンパイラエラーが発生します。 C#コンパイラチームは、その可能性を認識してコンパイラエラーにするのに十分なほどスマートでした。

イベントはマルチキャストデリゲートの特殊なタイプであるため、イベントにハンドラーを+=すると、呼び出しリストに追加されます。この場合、+=および-=を使用してイベントハンドラーを追加または削除する方が理にかなっていると思います。

OOPクラスを誰が教えたかはわかりませんが、すべてをget/setメソッドに削減する必要はありません。NETは、プロパティを使用してget/set型へのアクセスをはるかに容易にしました。単一の構成にget/setメソッドを含めます。

VB.NETは、目的に合わせてイベントを追加および削除するために、少し異なる構文を使用します。彼らは AddHandlerおよびRemoveHandler メソッドを使用してイベント呼び出しリストに追加または削除しますが、C#プログラマーですがVB =スタイル「長い風」。

8
Ron Beyer

イベントは単に専門的な代理人です。代議員の場合、=does過去の登録を削除します。同様に+他の多くの言語と同様に、関数合成を実行します。そう +=は、これらの操作を機能的な追加に結合します。

イベントはたまたま他の操作を制限するだけで、それらがどこから来たのかわからないので、直感的ではありません。

1
Telastyn

簡単な答え:なぜそうしないのですか?

同じイベントに複数のハンドラーが存在する可能性があるという概念にサブスクライブする場合、なぜ最も冗長なオプションを使用しないのですか?

私はC#の神であるEric Lippertと意見の相違がある非常に薄い氷の上にいることを知っていますが、それは常に私にとって非常に自然な構文のように思えました。あなたの通常の選択言語がPythonまたは他の言語である場合、私はこれがそれほどそうでないかもしれないことを見ることができます。

しかし、私は彼がそれが一種の突き出ていることを主張します。この構文を使用せざるを得ない言語のどこにも思いつきません。

0
Robbie Dee

C#では、フィールドがあり、基本的にカプセル化されたフィールドであるプロパティもあります。プロパティは一般的にフィールドを使用して実装されます(そして言語にはそれを簡潔に行うためのショートカットがあります)が、そうである必要はありません。

したがって、両方を書くことができます:

o.Field = 42;
o.Property = 42;

しかし、後者は実際には、setterメソッドの呼び出しにコンパイルされます。

o.set_Property(42);

フィールドとプロパティのもう1つの違いは、refの使用など、一部の操作がプロパティで許可されないことです。


デリゲートおよびイベントと同様です。イベントはカプセル化されたデリゲートフィールドです。イベントは一般的にデリゲートフィールドを使用して実装されます(言語には簡潔に実行するためのショートカットがあります)が、そうである必要はありません。

また、両方を記述できます。

o.DelegateField += Handler;
o.Event += Handler;

ただし、後者は実際には、adderメソッドの呼び出しにコンパイルされます。

o.add_Event(Handler);

もう1つの違いは、イベントでは、割り当てや呼び出しなど、ほとんどの操作が許可されないことです(宣言クラス自体からフィールドのようなイベントを呼び出すことを除く)。


だから、今の質問は:なぜデリゲートフィールドで+=を使用できるのですか?これは、デリゲートを結合するために+を使用できるためです。つまり、o.DelegateField += Handler;o.DelegateField = o.DelegateField + Handler;の省略形にすぎません。

イベントでは、イベントを読み取ったり、割り当てたりすることができないため、省略形の+=構文が唯一のオプションです。

0
svick