イベントを宣言する好ましい方法


14

.NETイベントモデルの理解にかなり満足しています。システムの小さなニュアンスを誤解しているのではないかと思います。

クラスにイベントを入れ始めたとき、次のような標準的な方法を使用します。

public event EventHandler<MyEventArgs> MyEvent;

これは、イベントにサブスクライブするものには、次のようなメソッドが必要であることを意味しました。

void HandleThatEvent(object sender, MyEventArgs args){...}

これは素晴らしいことですが、送信者を気にすることはめったにないため、多くのメソッドシグネチャが肥大化しました。

だから私は自分のデリゲート型の宣言に切り替えました

public delegate void MyEventHandler(SomeClass argument);

これにより混乱が減りましたが、ハンドラーの作成に関して小さな問題が残りました。

eventImplmentor.MyEvent += HandleThatEvent;
.
.
.
void HandleThatEvent(/*oh, um, what arguments does it take? Intellisense isn't telling me*/)

だから私はデリゲートの宣言に戻って見て、そして戻ってそれらを書くか、それをコンパイルして言われるのを待たなければなりません。

だから今、代わりに、私はちょうどActionAction<T>または適合するテンプレートを使用しています。

public event Action<SomeClass> MyEvent;

イベントにカーソルを合わせて、どのパラメーターが期待されるかを知ることができます。

私の質問、結局のところ:C#でイベントを宣言するためのベストプラクティスはありますか?EventHandler<T>道に戻る必要がありAction<T>ますか、それとも容認できますか?


イベントを発生させる場所にハンドラーがローカルにコピーされることを忘れないでください。スレッドセーフのために常にこれを実行する必要があります。
スヌープ

カプセル化されたコードで独自のスマート、平均、無駄のないタイプセーフイベントを記述できますが、公開するものはすべて標準パターンに従う必要があります。そうしないと、クラスのユーザーを混乱させることになります。
マーティンマート

回答:


8

単純な内部イベント処理には、提案しているように単にActionまたはを使用するものがありAction<T>ます。内部イベントでも、Senderを含む標準パターンを使用する傾向があります。これは、後でクラスまたはイベントを公開するタイミングがわからないため、イベントメソッドをリファクタリングするだけで済むというペナルティはないからですそれは公開。

イベント処理のシグネチャは単純なシナリオの場合よりも少し重いですが、追加のイベント引数が時間とともに必要になる可能性があるため、増分移行を処理するように設計されていることに同意します。全体として、特にお気付きのとおり、適切なIntelliSenseサポートを取得するのはあなただけなので、標準パターンに固執します。

それが価値があるので、私はこれに時間を割いて、別のイベント処理パターンを思いつきました。ここでの目標は、Senderを削除することではTSenderなく、として弱く型付けするのではなく、一般的に強く型付けするようにすることSystem.Objectでした。とてもうまくいきます。ただし、これを行うとIntelliSenseのサポートが失われるため、残念ながらトレードオフが発生します。

全体として、標準パターンに固執しますが、これを行うための潜在的に優れた方法を考えることは興味深いです。


あなたのSOの質問を教えてくれてありがとう。とても面白いです。送信者が必須であることがなぜそれほど重要であるのか、私はまだ理解していません。ほとんどの場合、送信者は気にしません。単なるarbitrary意的なMSルールですか?
マットエレン

いいえ、もちろん、好きなようにデリゲートを宣言できます。常に送信者を含めることが.NETのポリシーであり、まったく悪い考えではありません。
ニール

@Neil:役に立つこともあることは理解していますが、特にMSがイベントを行うことをお勧めしているため、常にそれを行うというポリシーはありません。イベントについて私が本当に気に入っていることの1つは、クラスを分離する機能です。オブジェクトを含めると、再び結合されます。それがただのCLSコンプライアンスのことなら、私はそれで生きることができます。
マットエレン

senderオブジェクトを使用する場合にのみ、再び結合されます。それ以外の場合は、senderオブジェクトを使用しないため、senderの値として何が設定されるかは関係ありません。依存関係は、依存関係が必要な場合にのみ存在します。あなたがどこから来たのかがわかります。オブジェクト送信者が地球上の任意のサーバーのすべてのコードから姿を消した場合、私は夜更かししません。
ニール

はい。本当に必要な場合は、送信者として「null」を送信できます...しかし、送信者を含めることにより、イベントハンドラ自体が必要に応じて登録を解除できます。ただし、全体的には、通常、イベントのソースを知ることは非常に重要だと思います。
マイクローゼンブラム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.