无操作订阅C#中的事件 - null检查冗余

时间:2015-10-13 11:47:28

标签: c#

所以,如果我在事件声明中做了类似的事情:

public event MyDelegate MyEvent = delegate { };

我读到这会使空检查变得多余,会有一个无操作用户。

我很好奇这是如何工作的。究竟发生了什么,这是一个很好的做法,还是应该在触发事件处理程序之前坚持使用常规的空值检查?

1 个答案:

答案 0 :(得分:4)

由于额外的if,空检查并不棘手 - 它们很棘手,因为它们在多线程环境中不可靠。

这是一种权衡。如果您希望事件只有0-1个委托,那么使用(安全)空值检查可能会更好。如果您希望有多个订阅者继续订阅和取消订阅,那么您最好使用" null-delegate"。它确实意味着在调用链中有一个额外的委托,但这对于.NET中大多数事件的使用来说通常都足够便宜。

你不想在例如使用它一个控件有50个不同的事件,其中大多数事件从来没有订阅者,或者你的行为会根据是否有订阅者而改变。

至于引擎盖下发生了什么,好吧......没什么。这没有任何魔力。诀窍在于+=如何处理事件/代理。

如果您有null事件并使用+=,则只需为该事件分配一个新委托。如果已有委托,它将创建一个新委托,它是前一个委托和新委托的组合。如果使用该null-delegate,它只是意味着总有一些委托要合并。调用事件的常用代码可能如下所示:

var ev = Click;

if (ev != null) ev();

这意味着如果事件没有订阅者,则不会调用。在null-delegate的情况下,代码进一步简化为

Click();

始终表示委托调用 - 至少会调用您的null委托。当然,它实际上并没有做任何事情,但是你保留了委托调用的开销。同样,这很少是一个问题,但有些情况下这是不可接受的。