C# - 为事件设置空委托


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");
        }
    }
}

好吧,你在这里给出的代码:

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。

另一种选择是使用扩展方法:

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>形式。

你不需要这样做。如果使用 class 的客户端不会为事件添加处理程序(订阅者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");
    }
}

相关内容

  • 没有找到相关文章

最新更新