2010-03-05 69 views
4

之間的區別 - 如果我定義與inital空委託的事件我不需要檢查空什麼是下面的代碼添加新的事件

class MyClass 
{ 
public event EventHandler<MyEventArgs> MyEvent = delegate { }; 

void SomeMethod() 
{ 
    ... 
    MyEvent(); // No need to check for null 
    ... 
} 
} 

- 否則我需要檢查空

class MyClass 
{ 
public event EventHandler<MyEventArgs> MyEvent; 

void SomeMethod() 
{ 
    ... 
    if (MyEvent != null) // No need to check for null 
    MyEvent(); 
    ... 
} 
} 

這些有什麼區別?在哪些情況下比另一個更好?

感謝

回答

3

的upvoted答案是明顯錯誤的,我要發佈一個答案。有人在互聯網上錯了,還不能上牀睡覺。

這很方便,但它不是免費的。編譯器必須爲匿名方法生成一個類,並且JIT編譯器必須爲其生成代碼。並且該代碼總是在引發事件時執行,無論客戶是否訂閱了事件處理程序。空檢查代碼也總是執行,但代碼和時間要少很多。

這不是很多代碼和很多時間。空檢查需要2個機器碼指令,並且應該在一個CPU週期內執行。匿名代表需要大約一個數量級,但在現代機器上仍然不是很多。就我個人而言,我太老了,不能像那樣浪費,兩個總是我的選擇。

沒有什麼,因爲這是標準模式,每個人都認識到它。

+0

總是附加虛擬事件處理程序的更糟糕的事情是委託處理方法和委託調用針對委託執行單一操作的情況進行了優化。將委託添加到null很容易,就像從它自己刪除委託一樣。儘管微軟設計了MultiCastDelegate以進行快速調用,但仍然存在一個額外的間接層,對於單個直接委派來說不是必需的。 – supercat

1

在我們公司,我們寫了鉤到大多數事件,並檢查它是否調用之前空的擴展方法。

我們減少了這一點:

var handler = MyEvent; 
if (handler != null) 
{ 
    handler(...); 
} 

MyEvent.SafeTrigger(...); 
+0

@Andy:檢查出這個線程:http://stackoverflow.com/questions/2282894/event-handler-raising-method-convention –

+0

是的,在SafeTrigger方法裏面就是它的功能。因爲SafeTrigger是擴展方法,所以如果MyEvent爲null,則擴展方法將獲得一個空參數。 –

2

第一個是適用的解決方案,但是它具有非常非常小的性能損失調用額外的空委託。

第二種解決方案不是線程安全的(如果它對你很重要,原因)。

你應該使用下列內容:

var handler = MyEvent; 
if (handler != null) 
    handler(this, new MyEventArgs()); 
+0

針對線程安全性的+1 –