7
private void NotifyFreeChannelsChanged() //1.
{
    if (FreeChannelsChanged != null)
    {
        FreeChannelsChanged(this, null);
    }
}

private void NotifyFreeChannelsChanged() //2.
{
    NotifyCollectionChangedEventHandler h = FreeChannelsChanged ;
     if (h != null)
         h(this, e);
}

これらのうち、どちらが優れているのか、そしてその理由。またはそれは単なる追加のチェックです。大きな違いではありません。

4

3 に答える 3

6

"より良い"?ええと、(特定の)競合状態は含まれていません。MultiCastDelegate型は不変であり、重要なすべての方法で値型のセマンティクスを使用します(ただし、これら参照型ですが、これを参照してください。さらに重要なことに、これを参照してください)。そのため、最初に割り当ててからチェックします。問題はそれです:

// this evaluates to true...
if(SomeEvent != null)
{
    // ...but before this line executes, the last 
    // subscriber detached, and now SomeEvent is null. Oops.
    SomeEvent(this, e);
}

「なぜ誰かが例2を使用するのか」と尋ねるべきでした。


余談ですが、これは暗黙的に型付けされた変数(var)を使用するのに最適な場所です。それらのデリゲートタイプ名は長くなります...

また、競合状態がまだ存在していることも興味深いです。それはもっと微妙です。割り当て後にサブスクライバーが削除された場合はどうなりますか?まあ、それはまだ呼び出されますが、あなたがそれについてできることは本当に何もありません(私は知っています)。

于 2013-02-22T08:24:32.147 に答える
1

2つ目は、EventHandlerがメソッドのターゲットである、使用する一連の拡張メソッドに簡単に役立ちます。

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

// And then...
TheEvent.Raise(this);

私の知る限り、ハンドラーをメソッドに渡すという事実は、競合状態を回避するためにそのローカルコピーを提供します。

于 2013-02-22T08:29:15.403 に答える
0

2つ目は、スニペット1でnullチェックとイベント発生の間でコンテキストスイッチが発生する可能性のあるスレッドバグから保護することです。他のスレッドがその間にnullに設定することができます。

したがって、メソッドがマルチスレッドになりがちでない限り、より単純なスニペットを使用できます。

于 2013-02-22T08:24:38.230 に答える