2010-05-07 88 views
5

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

因爲有連接到事件的方法這種長期工作原理,但如果沒有,則會拋出一個空引用異常。我究竟做錯了什麼?

回答

10

推薦的方法來調用一個事件是

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

0

如果某個事件在觸​​發時未訂閱,則會拋出NullReferenceException。這是正確的行爲,而不是你做錯了。

您應該檢查:

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

調用之前必須檢查,如果事件是空的事件:

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

DoorsChangeState爲空,這意味着有該事件沒有偵聽。

0

您需要檢查事件是否已訂閱。

我使用這個標準表格來拋出所有的事件。

var temp = EventName; 
if(EventName!= null) 
    temp(this, null); 
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); 
    } 
} 
+0

+1這使得一個非常好的語法! – MPritchard 2010-05-07 07:35:43