关于自定义事件的问题

时间:2010-05-07 06:47:26

标签: c# .net events

我正在为C#制作自定义事件,有时它无效。

这就是我发生事件的方式:

    private bool isDoorOpen;
    public bool IsDoorOpen {
        get { return isDoorOpen;}
        private set { isDoorOpen = value; DoorsChangeState(this, null);}
    }

这些是事件声明:

    //events        
    public delegate void ChangedEventHandler(Elevator sender, EventArgs e);
    public event ChangedEventHandler PositionChanged;
    public event ChangedEventHandler DirectionChanged;
    public event ChangedEventHandler BreaksChangeState;
    public event ChangedEventHandler DoorsChangeState;

只要有事件附加方法,这就有效,但如果没有,则抛出空引用异常。我做错了什么?

5 个答案:

答案 0 :(得分:10)

调用活动的推荐方法是

var handler = this.DoorsChangeState;
if (handler != null)
    handler(this, null);

在本地复制处理程序的原因是在检查null时,在另一个线程上更改事件处理程序。

编辑:发现文章谈论竞争条件。 http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

答案 1 :(得分:4)

我知道这个问题已经在SO上多次讨论(和回答)。

在这里的某处,我还有以下扩展方法,使这个模式更容易使用:

public static class EventHandlerExtensions
{
    public static void FireEvent<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
    {
        var temp = handler;
        if (temp != null)
        {
            temp(sender, args);
        }
    }

    public static void FireEvent(this EventHandler handler, object sender)
    {
        var temp = handler;
        if (temp != null)
        {
            temp(sender, EventArgs.Empty);
        }
    }
}

因此,在您的代码中,您可以说:

public bool IsDoorOpen
{
    get { return isDoorOpen;}
    private set
    {
        isDoorOpen = value;
        DoorsChangeState.FireEvent(this);
    }
}

答案 2 :(得分:0)

如果事件在触发时未订阅,则会抛出NullReferenceException。这是正确的行为,而不是你做错了。

你应该检查:

if(DoorsChangeState != null)
{
   DoorsChangeState(this, null); // Only fire if subscribed to
}

答案 3 :(得分:0)

在调用事件之前,您必须检查事件是否为null:

if (DoorsChangeState != null)   
  DoorsChangeState(this, null);

DoorsChangeState为空时,表示该事件上没有侦听器。

答案 4 :(得分:0)

您需要检查事件是否已订阅。

我使用这个标准表格来投掷我的所有活动。

var temp = EventName;
if(EventName!= null)
   temp(this, null);