为什么“公共事件EventHandler cccc”为空?

时间:2010-06-17 18:35:22

标签: c# .net events

为什么'公共事件EventHandler cccc'为空?

我有一个班级

public class Builder
{
    public event EventHandler StartedWorking;

    public Builder()
    { 
        // Constructor does some stuff
    }

    public void Start()
    {
       StartedWorking(this, eventargobject); //StartedWorking is null --
    }
}   

这看起来很简单,我一直在做什么?我错过了一些明显的东西,或者是否有可能导致这种情况的东西?

编辑:

这是否意味着如果我在客户端类中触发未订阅的事件,我必须检查它是否为空?

EDIT-2:

我想我从未有过从未订阅的事件,因此从未遇到过 - 你每天学习新的东西 抱歉看似愚蠢的问题......

4 个答案:

答案 0 :(得分:12)

除非有人订阅了该事件,否则事件处理程序将为null。一旦委托订阅了该事件,它就不再是空的。

这就是为什么总是建议使用以下表格来举起活动:

public void Start()
{
    var handler = this.StartedWorking;
    if (handler != null)
    {
         handler(this, eventArgObject);
    }
}

如果没有订阅者,这可以保护您免受空异常。

答案 1 :(得分:2)

正如其他人已经说过的那样,它是空的,因为没有订阅者。

要回答您的编辑:是的,您应该在触发事件之前检查事件是否为null。但是,如果你只是做一个简单的if(StartedWorking != null){...},你就会面临竞争条件,因为订阅者可能会在空检查之后但在你触发事件之前取消订阅。因此,在检查null的事件时应始终使用此模式:

protected void OnStartedWorking()
{
    EventHandler localEvent = StartedWorking
    if(localEvent != null)
    {
        localEvent(this, EventArgs.Empty);
    }
}

这可以通过首先获取事件的副本来防止竞争条件,从而在复制点修复订阅列表。

有关在MSDN上发布活动的更多信息:How to Publish Events that Conform to .NET Framework Guidelines

(这是因为.net中的MultiCastDelegate类在imutable中,因此任何更改事件上的订阅者列表的尝试都不会影响您所做的副本)

答案 2 :(得分:0)

如果您尚未将任何事件订阅者挂钩到您的StartedWorking事件,那么它将为null。这就是.NET事件的工作原理。

除其他事项外,

This article表明在调用事件之前应检查null。 This other question and answer演示了如何以避免空检查的方式创建事件(基本上通过总是添加空处理程序)。

答案 3 :(得分:0)

您不需要分配功能吗?

StartedWorking += new EventHandler(afunction);

void afunction(object sender, EventArgs e)
{
   DoSomething();
}