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