2012-03-19 31 views
4

習慣了VB.NET,我習慣於「只是引發事件」。當然,自定義事件有所不同,但對於「常規」事件 - 我不需要在籌集之前檢查代表是否爲Nothing用C#舉辦活動:性能和優雅

在C#中,我發現自己重複這種模式:

if (myHandler != null) 
{ 
    myHandler(this, new EventArgs()); 
} 

我在想,下面的模式可能被證明更優雅:myHandler = (sender, e) => { };

  1. 將myHandler與空拉姆達初始化
  2. myHandler預計永遠不會爲空,因此提高會變成:myHandler(this, new EventArgs());

這個模式會比上一個更好或更差嗎? 我應該考慮其他重要考慮因素嗎?

+2

查看回答這個非常類似的問題:http://stackoverflow.com/questions/170907/is-there-a-downside-to-adding-an-anonymous-empty-delegate-on-event-declaration – 2012-03-19 07:47:18

+0

錯過了那個,thanx! – 2012-03-19 08:04:58

回答

1

我認爲這兩種方法之間的性能差異不夠大是相關的。如果有的話,我會爭辯說,即使它是無操作的,通過代理調用方法,空檢查是更便宜

在談到優雅,應該指出的是,在VB.NET is automatically expanded by the compilerRaiseEvent關鍵字精確,你必須自己寫在C#中同一構造:

If (Not MyEvent Is Nothing) Then 
    MyEvent.Invoke(New EventArgs()) 
End If 

如果你想避免

public static void RaiseEvent(this EventHandler source, object sender) 
{ 
    if (source != null) 
    { 
     source.Invoke(sender, new EventArgs()); 
    } 
} 

public static void RaiseEvent<T>(this EventHandler<T> source, object sender, T eventArgs) 
    where T : EventArgs 
{ 
    if (source != null) 
    { 
     source.Invoke(sender, eventArgs); 
    } 
} 

這樣,你可以簡單地說:重複整個代碼結構,你可以在一對夫婦的擴展方法將其封裝

myEvent.RaiseEvent(this); 
myOtherEvent.RaiseEvent(this, new SomeEventArgs()); 

它在語義上等同於VB.NET中使用的風格。

1

不要認爲提供的第一和第二種情況之間存在顯着差異,至少沒有太多考慮它們。 太頻繁使用代表缺乏if (myHandler != null)可能,順便說一句,你有一些性能好處。所以如果你確定處理器是從來沒有null,擺脫這種控制,基本上你做了。

5

這是在施工中發生的額外事情,但它不會是巨大的開銷。有一點需要注意,像DataContractSerializer(WCF)這樣的一些序列化框架不會運行構造函數或字段初始值設定項,所以它可能不是非null。就個人而言,如果你的大多數事件都EventHandler,我可能會嘗試使用擴展方法:

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

則:

SomeEvent.SafeInvoke(this); 

但坦率地說,我很少有一個問題,只需使用null-check; p

另一個缺點是,如果您有足夠的事件發生此問題,則應該使用EventHandlerList代替 - 而且此方法不適用於EventHandlerList

2

常見的做法是使用受保護的虛擬方法的OnEventName在那裏你可以檢查,如果事件爲null,提高它:

protected virtual void OnEventName(parameters) 
{ 
    if (EventName != null) 
     EventName(this, new EventNameEventArgs(parameters); 
} 

這可以讓你在一個地方的所有事件,提高代碼(沒有空檢查重複),如果需要,稍後覆蓋它。所以我沒有看到爲每個事件添加一個虛擬事件處理程序而不是每個事件有一個空檢查的好處。

BTW短的方式來增加虛擬處理器是myHandler = delegate {};