关于自定义事件的问题

问题描述:

我正在为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; 

因为有连接到事件的方法这种长期工作原理,但如果没有,则会抛出一个空引用异常。我究竟做错了什么?

推荐的方法来调用一个事件是

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

之所以本地复制的处理程序是,当你检查空另一个线程柜面事件处理程序的变化。

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

+0

+1没有意识到线程安全问题以及事件不可变的事实。感谢您的链接。 – 2010-05-07 07:02:25

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

您应该检查:

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

调用之前必须检查,如果事件是空的事件:

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

DoorsChangeState为空,这意味着有该事件没有侦听。

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

我使用这个标准表格来抛出所有的事件。

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

我知道这个问题已经在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); 
    } 
} 
+0

+1这使得一个非常好的语法! – MPritchard 2010-05-07 07:35:43