1
public event EventHandler MyButtonClick = delegate { };

上記の構成により、サブスクライバーが存在するかどうかをチェックしないようにすることができます。

public virtual void OnMyButtonClick(EventHandler e)
        {
            this.MyButtonClick(this, e);
        }

それ以外の

  public virtual void OnMyButtonClick(EventHandler e)
            { 
                if (MyButtonClick!=null)
                   this.MyButtonClick(this, e);
            }

しかし、それは本当に良い考えですか?サブスクライバが存在するかどうかを確認しないという利点はこれだけですか?

更新:これが例です

namespace ConsoleApplication2
{
    public class TestClass
    {
        public event EventHandler MyButtonClick;
            //= delegate { };

        public void OnButtonClick(EventArgs e)
        {
            MyButtonClick(this, e);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var testClass = new TestClass();
            //it throws an exception
            testClass.OnButtonClick(new EventArgs());

            // if you add an handler it will call it

            testClass.MyButtonClick += myCustomHandler;
            testClass.OnButtonClick(new EventArgs()); // myCustomHandler has been invoiked

        }

        private static void myCustomHandler(object sender, EventArgs e)
        {
            Console.WriteLine("myCustomHandler has been invoiked");
        }
    }
}
4

2 に答える 2

4

さて、あなたがここに与えたコード:

public virtual void OnMyButtonClick(EventHandler e)
{ 
    if (MyButtonClick!=null)
       this.MyButtonClick(this, e);
}

スレッドセーフではありません。無効性チェックの、呼び出しの前に最終的なサブスクリプションが削除された場合、 NullReferenceException(「発生」スレッドが変更を確認するかどうかに応じて) になる可能性があります。

したがって、代わりに次のように変更できます。

public virtual void OnMyButtonClick(EventArgs e)
{ 
    var handler = MyButtonClick;
    if (handler != null)
    {
        handler(this, e);
    }
}

...しかし、もちろん、それを忘れる可能性があります。そうしない場合でも、あちこちでそれを行うのは面倒です.IMO. そうです、メリットは無効チェックを回避するための「唯一の」ものですが、多くの場合、それは悪いトレードオフではないと思います。間違いを犯しにくくするものは何でも良い考えです、IMO.

もう 1 つの方法は、拡張メソッドを使用することです。

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

次に、呼び出しコードを次のように変更します。

public virtual void OnMyButtonClick(EventArgs e)
{
    MyButtonClick.SafeInvoke(this, e);
}

(他のイベントにも同じコードを使用します)。おそらく、一般的なフォームEventHandler<T>も必要になるでしょう。

于 2012-07-23T16:41:28.083 に答える
0

あなたはそれをする必要はありません。あなたのクラスを使用するクライアントがMyButtonClickイベントのハンドラー(サブスクライバー)を追加しない場合、コードは例外をスローしません。

これがイベントの仕組みです(同じことがあるので委任します)。そうしないと、クラスのすべてのイベントにハンドラーを追加する必要があります(イベントがあると仮定して)

だからあなたは以下を行うことができます:

public virtual void OnMyButtonClick(EventArgs e)
{ 
   MyButtonClick(this, e);
}

以下の例をご覧ください。

public class TestClass
{
    public event EventHandler MyButtonClick = delegate { };

    public void ButtonClick(EventArgs e)
    {
        MyButtonClick(this,e);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var testClass=new TestClass();
        testClass.ButtonClick(new EventArgs());

        // if you add an handler it will call it

        testClass.MyButtonClick += myCustomHandler;
        testClass.ButtonClick(new EventArgs()); // myCustomHandler has been invoiked

    }

    private static void myCustomHandler(object sender, EventArgs e)
    {
        Console.WriteLine("myCustomHandler has been invoiked");
    }
}
于 2012-07-23T08:58:36.620 に答える