2010-06-03 67 views
9

我剛剛意識到我不完全理解爲什麼在.NET中使用+ =符號分配事件。如何在.NET中分配事件

昨天我想通了這一點,當我需要刪除的事件,我想都沒想就在做

someobject.onsomeevent += null 

思想,只會刪除我以前分配的事件。

經過一番調查後,我想通了,我不得不

someobject.onsomeevent -= someeventmethod; 

搞清楚了這一點後,我意識到我不明白事件的方法是如何在.NET中分配。

所以,我有幾個問題:

首先,它意味着,如果是這樣,當發生onsomeevent他們都將被打到,並在指定的順序,我可以做

someobject.onsomeevent += someeventmethod; 
someobject.onsomeevent += someeventothermethod; 

或同時?

此外,如何確定哪些事件方法已被分配到someobject.onsomeevent

其次,有沒有辦法在某些類中保存事件方法,將它們從someobject.onsomeevent中移除並在通常會觸發事件的其他過程完成後重新分配它們?

+1

混亂,你應該嘗試長( .NET 1.x)form:'someobject.onsomeevent - = new Eventhandler(someeventmethod);' – 2010-06-03 19:45:29

+0

這麼多好的答案!謝謝大家! – Matt 2010-06-03 20:01:36

回答

3

第一個問題:只要方法簽名與事件的委託類型兼容,您就可以做到。

第二個問題:是的,你也可以這樣做。使用EventTest.GetInvocationList()來獲取註冊到您的事件的方法。然後分別使用-=+=刪除並重新添加委託。請參見下面的示例:

public class Test 
    { 
     public event EventHandler EventTest = delegate { }; 
     public void Method() 
     { 
      //get registered event handlers 
      Delegate[] invocationList = EventTest.GetInvocationList(); 

      //remove them 
      foreach (Delegate d in invocationList) 
      { 
       EventTest -= (EventHandler)d; 
      } 

      //this method won't trigger anything, because 
      //invocation list is empty 
      Method2(); 

      //re-add event handlers 
      foreach (Delegate d in invocationList) 
      { 
       EventTest += (EventHandler)d; 
      } 
     } 

     public void Method2() 
     { 
      if(EvenTest != null) 
      EventTest(this, EventArgs.Empty); 
     } 
    } 

我除去瑣碎Main() -method使代碼更具有可讀性。

4

關於你的第一個問題:默認情況下你獲得多播行爲。也就是說,如果您有多個處理程序,那麼默認情況下,將按順序調用事件處理程序(除非其中一個拋出異常)。請注意,您可以更改add+=)和remove-=)以執行與默認行爲不同的操作。

Jon Skeet有一個頁面解釋你可能想要閱讀的delegates and events in C#

2

所以答案是肯定的,並按順序添加。

事件是MulticastDelegate類的一個實例。要找出分配給事件的代理,請調用事件的GetInvocationList方法。請參閱http://msdn.microsoft.com/en-us/library/system.multicastdelegate.getinvocationlist%28v=VS.71%29.aspx

這將爲您提供一組代表。所以你可以調用GetInvocationList來獲取現有的事件處理程序;然後清除事件中的事件處理程序;執行一些操作;然後重新分配處理程序回到事件。

2

代表是.NET中的「多播」,事件是類似於屬性的包裝器。

private EventHandler _handler; 

public event EventHandler MyEvent 
{ 
    add { _handler = (EventHandler)Delegate.Combine(_handler, value); } 
    remove { _handler = (EventHandler)Delegate.Remove(_handler, value); } 
} 

你通常會寫上述所有的1號線:

public event EventHandler MyEvent; 

而且是完整的,事件可以通過查看長形符號的事件得到更好的undestanding建立一個觸發時按順序處理的調用列表。沒有關於訂單的保證。

2

而只是爲了掩飾一個位,我不認爲任何人都顯式地處理,該事件不火都在同一時間 - 他們開火順序...