C# 当没有订阅服务器时,为什么委托是空的而不是空的列表?

C# 当没有订阅服务器时,为什么委托是空的而不是空的列表?,c#,.net,events,delegates,C#,.net,Events,Delegates,有人能解释一下为什么.Net framework团队决定没有订阅者的委托应该为null,而不是调用列表为空的对象吗?我想知道导致这一决定的理由 void DoSomething() { EventHandler handler = SomeEvent; if(handler != null) //why is this null-check necessary? { handler(this, EventArgs.Emp

有人能解释一下为什么.Net framework团队决定没有订阅者的委托应该为null,而不是调用列表为空的对象吗?我想知道导致这一决定的理由

void DoSomething()
{
    EventHandler handler = SomeEvent;
    if(handler != null)                   //why is this null-check necessary?
    {
        handler(this, EventArgs.Empty);
    }
}

谢谢

我同意这可能会很麻烦,我个人认为这是一个错误。我想不出为什么会这样。

在CLR级别,委托字段和事件字段是常规字段


就像
string MyField
默认为
null
而不是
一样,
Action MyField
也默认为
null
,而不是空的
Action
实例。

有关这方面的详细讨论,请参见Jon Skeet的答案。甚至可以避免在C#2.0中检查null。

使用null处理空列表在运行时是有效的,特别是因为绝大多数事件都有零或一个订阅者。C#中的缺陷不是使用
null
来处理空列表,而是在许多上下文中,事件名称指的是委托而不是事件。更好的设计应该使用前面的下划线或其他前缀命名委托,然后只允许使用事件名称的特定操作:

  • 订阅
  • 退订
  • 调用(如果非null,则应调用_eventName,否则不执行任何操作) 对于所有其他事件操作,必须使用
    \u eventName
    。与要求用户代码复制事件委托、测试是否为null以及调用复制(如果不是)相比,这样的设计将节省数不清的数千行(如果不是数百万行)代码