59

悪か悪か?

public static void Raise(this EventHandler handler, object sender, EventArgs args)
{
   if (handler != null)
   {
      handler(sender, args);
   }
}

// Usage:
MyButtonClicked.Raise(this, EventArgs.Empty);

// This works too! Evil?
EventHandler handler = null;
handler.Raise(this, EVentArgs.Empty);

拡張メソッドの性質上、MyButtonClicked が null の場合、MyButtonClicked.Raise は NullReferenceException をスローしないことに注意してください。(たとえば、MyButtonClicked イベントのリスナーはありません)。

悪かどうか?

4

8 に答える 8

35

悪ではない。イベントがデフォルトでこのように機能することを望みます。サブスクライバーのないイベントが null である理由を誰かが説明できますか?

于 2008-10-29T19:24:28.663 に答える
14

イベントはいつでも次のように宣言できます (お勧めしません)。

public event EventHandler<EventArgs> OnClicked = delegate { };

そうすれば、呼び出し時に何かが割り当てられるため、null ポインター例外がスローされません。

おそらく、C# 3.0 でデリゲート キーワードを取り除くことができます...

于 2008-10-29T19:29:18.293 に答える
9

を使用することを忘れないでください[MethodImpl(MethodImplOptions.NoInlining)]。そうしないと、スレッドセーフではない可能性があります。

(ずっと前に読んで、思い出して、グーグルで見つけましたhttp://blog.quantumbitdesigns.com/tag/events/

于 2008-11-16T03:19:44.273 に答える
6

Java の背景を持つ私にとって、これはいつも奇妙に思えました。イベントを聞いている人は誰も完全に有効ではないと思います。特に、リスナーが動的に追加および削除される場合。

私には、これは、人々が毎回nullを知らない/忘れたときにバグを引き起こすC#の落とし穴の1つに思えます。

この実装の詳細を非表示にすることは、毎回 null をチェックするための読みやすさに役立たないため、良い計画のようです。MSFTは、誰も聞いていない場合にイベントを構築しないことでパフォーマンスが向上すると確信していますが、ほとんどのビジネスコードで無意味なヌルポインター例外/可読性の低下が大幅に上回っています。

また、次の 2 つのメソッドをクラスに追加します。

    public static void Raise(this EventHandler handler, object sender)
    {
        Raise(handler, sender, EventArgs.Empty);
    }

    public static void Raise<TA>(this EventHandler<TA> handler, object sender, TA args)
        where TA : EventArgs
    {
        if (handler != null)
        {
            handler(sender, args);
        }
    }
于 2008-11-11T11:48:40.947 に答える
5

なぜそれが悪になるのですか?

その目的は明らかです。MyButtonClicked イベントを発生させます。

関数呼び出しのオーバーヘッドが追加されますが、.NET では最適化されるか、いずれにせよ非常に高速になります。

少し些細なことですが、C# に対する私の最大の不満を解決してくれます。

全体として、それは素晴らしいアイデアだと思います。おそらくそれを盗むでしょう。

于 2008-10-29T19:27:02.993 に答える
0

それを悪とは言いませんが、不要なオーバーヘッドが追加されるため、依然としてマイナスの影響があります。

通話時

myEvent.Raise(this, new EventArgs());

オブジェクト EventArgs は、誰も myEvent をサブスクライブしていない場合でも、すべての状況で初期化されます。

使用時

if (myEvent!= null) {
   myEvent(this, new EventArgs());
}

EventArgs は、誰かが myEvent をサブスクライブした場合にのみ初期化されます。

于 2010-02-18T11:04:27.433 に答える
0

私はそれが悪だとは言いませんが、あなたの拡張メソッドがどのように適合するかに興味があります

protected virtual OnSomeEvent(EventArgs e){ }

パターンと、継承による拡張性を処理する方法。メソッドをオーバーライドする代わりに、すべてのサブクラスがイベントを処理すると思いますか?

于 2008-10-29T19:32:22.953 に答える
-2

ハンドラーがないときに例外をスローすることは、ほとんどの場合、あまり好ましくありません。ハンドラーがない場合は、null よりも空にすることをお勧めします。

于 2011-09-07T07:24:05.227 に答える