2009-07-21 92 views
0

也許一個愚蠢的問題,但..這是危險的嗎?關於事件

在我的代碼中,我在幾個地方使用以下構造。

void MyFunction() 
{ 
    DoSomething(myClass.myProperty) 

    myClass.PropertyChanged += (s,e) => { 
     if (e.PropertyName == "myProperty") { 
     DoSomething(myClass.myProperty); 
     } 
    } 
} 

所以我最初想做一些事情,並且在未來的財產變化時也這樣做。

現在事情是,我的程序執行過程中MyFunction()會被調用幾次。我將分配給PropertyChanged的委託添加到它通過此方法的加班嗎? (每次迭代消耗更多內存並減慢程序速度)或者是編譯器/運行時足夠聰明以理解我應該只在第一次添加..?如果是這樣,這是如何工作的?

+0

這對您來說可能不是問題,但是使用這種語法不可能從此事件中取消訂閱匿名事件處理程序,這可能會導致一些內存問題。我建議編寫函數,並將事件處理程序與+ = new eventhandler(function)相關聯; – 2009-07-21 13:59:57

回答

3

許多其他的答案建議你應該檢查PropertyChanged事件是否是null防止增加幾個聽衆。該解決方案的一個問題是,如果代碼的其他部分監聽同一個事件,但是監聽另一個屬性,則此PropertyChanged可能不是null

void AnotherFunction() 
{ 
    myClass.PropertyChanged += (s,e) => { 
    if (e.PropertyName == "anotherProperty") { 
     DoSomethingElse(myClass.anotherProperty); 
    } 
    } 
} 

更好的解決方案,在我看來,是保持一個布爾標誌,它最初是假的,只有當MyFunction被稱爲設置爲true。然後,檢查這個標誌是否需要添加事件處理程序。

4

編譯器無法知道您的意圖......它將忠實地附加每次調用MyFunction()的事件處理程序。

這樣看 - 它們的編譯器無法知道函數中的引用變量(例如myclass)是否指向您之前附加處理程序的對象的相同實例。它也不知道你在呼叫之間的其他地方沒有分開處理程序。它不能做出這樣的假設。

但是,您可以重構您的代碼,以便該處理程序僅附加一次。由於其他消費者可能會訂閱PropertyChanged事件,因此需要保留一些獨立的狀態以瞭解您是否已訂閱或未訂閱。例如:

if(!haveSubscribedToPropertyChanged) { 
    myClass.PropertyChanged += (s,e) => { 
      if (e.PropertyName == "myProperty") { 
       DoSomething(myClass.myProperty); 
      } 
     } 
     haveSubscribedToPropertyChanged = true; 
     } 
+0

謝謝。這裏的一個問題也是myClass是一個單例,也可以從其他方法訪問。所以其他人也可以添加他們的代表。我也需要爲此找到一些東西。 – 2009-07-21 12:33:23

+0

檢查null的解決方案對於PropertyChanged事件不可行,因爲代碼的其他部分可能使用相同的事件來偵聽對不同屬性的更改。看到我的答案不同的解決方案:http://stackoverflow.com/questions/1158849/is-this-dangerous-about-events/1158930#1158930 – 2009-07-21 12:40:20