13

私が見たほとんどのコードは、次の方法を使用してイベントの発生を宣言および呼び出します。

public class MyExample
{
    public event Action MyEvent; // could be an event EventHandler<EventArgs>, too

    private void OnMyEvent()
    {
        var handler = this.MyEvent; // copy before access (to aviod race cond.)
        if (handler != null)
        {
            handler();
        }
    }

    public void DoSomeThingsAndFireEvent() 
    {
        // ... doing some things here
        OnMyEvent();
    }
 }

ReSharperでさえ、上記の方法で呼び出しメソッドを生成します。

なぜこのようにしないのですか?

public class MyExample
{
    public event Action MyEvent = delegate {}; // init here, so it's never null

    public void DoSomeThingsAndFireEvent() 
    {
        // ... doing some things here
        OnMyEvent(); // save to call directly because this can't be null
    }
 }

誰かがこれをしない理由を説明できますか?(賛否両論)

4

4 に答える 4

19

長所と短所は次のとおりです。

  • null チェックは非常に安価です。私たちは10億分の1秒を話している. デリゲートを割り当ててから、オブジェクトの残りの有効期間のガベージ コレクションに失敗すると、数百万分の 1 秒以上かかる可能性があります。さらに、数十バイト多くのメモリを消費しています。さらに、イベントが発生するたびに、何もしないメソッドへの不要な呼び出しが発生し、さらに多くのマイクロ秒が消費されます。あなたが数百万分の 1 秒と数十バイトを気にするような人なら、それは意味のある違いかもしれません。ほとんどの場合、そうではありません。

  • 常に空のデリゲートを作成することを忘れないでください。nullをチェックすることを覚えておくよりも本当に簡単ですか?

  • どちらのパターンも実際にはイベントをスレッドセーフにしません。どちらのパターンでも、イベント ハンドラーが 1 つのスレッドで起動され、別のスレッドで削除される可能性は依然としてあります。つまり、競合が発生します。ハンドラー削除コードがハンドラーが必要とする状態を破棄する場合、別のスレッドがハンドラーを実行している間に、あるスレッドがその状態を破棄している可能性があります。null をチェックしたり、空のハンドラーを割り当てたりするだけで、魔法のように競合状態が解消されるとは思わないでください。null の逆参照につながる競合状態を排除するだけです。

于 2012-04-23T14:51:20.733 に答える
7

それは確かにスタイルの問題です。ただし、null チェックに関しては、ほとんどの開発者はスタイルよりも安全性を優先すると思います。 バグがシステムに忍び込まず、null チェックが不要であり続けることを保証できるものは、この世界には何もありません。

于 2012-04-23T14:09:13.287 に答える
6

null のままにすることもできます。検討:

    var x = new MyExample();
    x.MyEvent += SomeHandler;

    // ... later, when the above code is disposed of

    x.MyEvent -= SomeHandler;

編集:実際には、私はそれを取り戻します。これをテストした結果、匿名デリゲートを使用してハンドラーを設定した場合、それをクリアできないように見えるため、null チェックを保存できます。

これが信頼できる動作なのか、それとも言語実装の単なるアーティファクトなのかはわかりません...

于 2012-04-23T14:05:30.860 に答える
3

イベントの発生を単純化するための最良のトレードオフは、拡張メソッドの追加です。拡張メソッドを使用して C# イベントを発生させるを参照してください - それは悪いことですか? .

于 2012-04-23T14:35:42.670 に答える