簡體   English   中英

為什么我可以檢查一些事件處理程序為null,有些不是嗎?

[英]Why can I check some event handlers for null, some not?

我有一段丑陋的代碼添加了事件處理程序。 問題是,如果多次調用代碼,則會多次調用事件處理程序。

要解決此問題,我先刪除事件處理程序然后添加它。

現在我已經看到以下行為:

可以檢查一些事件處理程序,如:

if (object.event == null) {
    //
    // Code
    //
}

其他形式

if (object.object.event == null) {
    //
    // Code
    //
}

我得到像'object.object.event'這樣的消息可能只發生在 - =或+ =之后。 (由於我使用的是德語版的visual studio,我不知道正確的英文翻譯)。

我不知道為什么這種行為看起來不合適所以我將不勝感激這方面的一些信息。

更具體一點:它是用戶控制。

if (myControl.Event == null) {
    //
    // works
    //
}

if (myControl.TreeView.NodeMouseClick == null) {
    //
    // doesn't work
    //
}

要解決此問題,我先刪除事件處理程序然后添加它。

這並沒有解決問題。 event關鍵字為委托對象提供訪問器。 就像一個屬性為一個領域提供訪問者。 在物業上,您總是需要一次獲取設置 事件具有添加,刪除和提升訪問者。 但是如果您自己不這樣做,編譯器將為它們生成默認實現。 這很常見。

屬性訪問器的優點是支持字段可以是私有的。 除了包含該字段的類之外,沒有人可以搞亂它。 所有訪問都必須通過get和set訪問器。 event關鍵字的工作方式完全相同,除了包含事件的類中的代碼之外,沒有人可以使用委托對象。

在你試圖避免引發事件的過程中,這是一個巨大的漏洞。 你不能搞亂在另一個類中聲明的事件的訂閱者列表,編譯器告訴你這個。 這樣做的正常方法是設置bool標志以指示必須暫時忽略事件。 事件處理程序可以檢查該標志並避免執行任何副作用。

您只能訪問班級中定義的事件的后備字段。
有關更多信息,請參閱規范 (雖然在C#4中有所改變 ,但這些變化與你無關)

method in each class. 在您的情況下,最佳做法是在每個類中創建protected internal On 方法。

SLaks是正確的,並與一些優秀的資源相關聯。 以下是Chris Burrows 博客文章的相關引用:

讓我快速繞道而行,向您解釋+ =的綁定如何在C#中起作用。 有兩種可能性:

  1. 或者有一個實際的+運算符,例如使用整數,並且x + = y綁定到“x = x + y”,除了x僅被計算一次。 這是復合賦值運算符; 要么
  2. 左邊的東西是一個事件,xE + = y綁定到“x.add_E(y)”。 這是事件訪問器操作符,實際上這是綁定到事件訪問器的唯一方法。

那么我們在上面的代碼片段中有什么? 好吧,您需要確定的額外細節是關於C#中類似字段事件的以下規則: 在類或結構之外定義類似字段的事件E,綁定到名稱E解析為事件本身,唯一合法的操作是調用訪問者; 在定義類似字段的事件E的類或結構內部,綁定到名稱E解析為私有委托字段

在你的情況,解決當myControl.Event ,你是里面 myControl類,所以你沒有看到的事件對象; 相反,您會看到一個實際的委托對象,您可以將其與null進行比較。 解析myControl.TreeView.NodeMouseClick ,您在TreeView之外 ,因此無法訪問實際的委托對象; 你得到的只是事件對象,無法與null進行比較。

如果我理解正確的話,所有這些對你來說都無濟於事,因為大概在你檢查null之后,你會嘗試為它啟動TreeView的事件,這是你無法做到的。

根據您要執行的操作,您可能會繼承TreeView並添加一個internal方法,該方法將調用受保護的TreeView.OnNodeMouseClick方法來觸發事件。

您只能查詢自己的事件處理程序以獲取附加的偵聽器。

自動事件,如下所示:

public event EventHandler SomethingHappened;

由編譯器使用多播委托實現。

當你編寫myControl.Event == null ,編譯器實際上需要在該委托上調用Delegate.GetInvocationList 編譯器不允許您這樣做,除非代碼在暴露事件的類的方法內,因此錯誤(它只允許您在調用列表中添加或刪除)。

如果我們在討論您在自己的類中定義的事件,那么您可以選擇公開調用列表(例如通過方法)並執行您要執行的操作。 但是對於現有的類(例如TreeView ),這是不可能的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM