在C#中,我们附加了一个事件处理程序,如下所示:
form1.Click += new EventHandler(form1_Click);
加号的意义是什么我知道我们可以为一个控件附加许多事件处理程序,因此+=
语法是有意义的。但我想我也应该能够写这样的东西:
form1.Click = new EventHandler(form1_Click);
这样我就可以覆盖以前的所有处理程序,只附加最后一个处理程序,但这不会编译。当然,我认为+=
运算符应该像处理字符串和int一样工作。为处理程序强制+=
的设计原则是什么换句话说,为什么我不能只写=
事件处理程序在内部由委托数组表示,因此正常的+=
&-=
运算符适用。
但是,您可以使用与=
一起直接分配的,但只能在定义事件的类中使用,这将删除所有以前的事件处理程序,取而代之的是您正在分配的那个事件处理程序。
在本文中,请查看发布和订阅部分。
在C#中,任何对象都可以发布一组其他类要发布的事件可以订阅。当发布类引发事件时,所有订阅的类会得到通知。
所以,你是一个订阅者,你不关心影响那些已经订阅的人的列表。这取决于出版商的能力。
如果你说这取决于程序员,那么你可以开发你的"发布者"类,这样它们就可以提供一些公共方法,让任何订阅者都有机会重置一些事件订阅。在框架中,它被设计所禁止。这也是某些程序员的决定。
类似
a += 2
这意味着
a = a + 2
如果我们做
a = 2
这将删除一个值,并将其替换为2。
类似
form1.Click += new EventHandler(form1_Click);
指
form1.Click = form1.Click + new EventHandler(form1_Click);
意味着将我们的事件处理程序添加到form1.click之前所做的操作中。
现在form1.Click将做它默认做的事情,也做我们希望它在form1_Click 中做的事情
如果我们写
form1.Click = new EventHandler(form1_Click);
这将删除所有以前的事件处理程序,只添加我们的form1_Click
因为当您使用event SomeHandler SomeEvent
语法定义event
时,它默认为您定义add
和remove
。这里的要点是,您与event
公开交互的唯一方式是通过add
和remove
(分别由+=
和-=
访问)。该语言不允许"全部重置"操作,这就是不允许=
的原因。
为了解决"设计选择"这一更深层的问题。。。我想驱动力是event
的契约——一种多播模型,用户可以自由添加和删除订阅。允许任何人取消订阅所有订户都将违反该合同,而只允许一个订户不是该合同。
附录:看起来您想要的是直接公开委托的能力,如果您只依赖.NET的多播委托语法,就可以做到这一点。它看起来很像event
语法,但允许使用=
进行清除,甚至足够聪明,可以理解null
delegate
上的+=
(见输出):
public delegate void F(int x);
public static void Main()
{
F f = null;
f += x => System.Console.WriteLine("First: {0}", x);
f += x => System.Console.WriteLine("Second: {0}", x);
f(5);
}
或者,您可以使用event
的长形式,使add
/remove
命中内部列表,并提供一种允许清除该列表的方法。
您可以没有、一个或很多,所以您可以使用+=
添加一个(订阅),或者使用opsite-=
删除(取消订阅)
form1.Click += new EventHandler(form1_Click);
// click here will execute form1_Click
form1.Click += new EventHandler(form1_Click2);
// click here will execute form1_Click1 AND form1_Click2
form1.Click -= new EventHandler(form1_Click1);
// click here will JUST execute form1_Click2
现在,强制使用+=将防止开发人员开枪自杀。我的意思是,使能够调用form1.点击=。。。来自任何其他类的代理将使一个用户能够无意中清除其他附加的代理。这就是默认情况下强制执行的原因。