2012-04-03 96 views
5

在實現其最基本的形式INotifyPropertyChanged接口,大多數人似乎實現它這樣的:INotifyProperyChanged - 爲什麼要額外分配?

public virtual void OnPropertyChanged(string propertyName) 
{ 
    var propertyChanged = PropertyChanged; 
    if (propertyChanged != null) 
    { 
     propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

我的問題是:爲什麼的var propertyChanged = PropertyChanged;額外分配?這只是一個偏好問題,還是有充分的理由?當然以下是有效的?

public virtual void OnPropertyChanged(string propertyName) 
{ 
    if (PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 
+1

http://stackoverflow.com/questions/786383/c-sharp-events-and-thread-safety – 2012-04-03 06:59:53

回答

4

分配給一個臨時變量消除了空校驗和上次事件訂閱,退訂之間的競爭條件的機會。請參閱.NET事件指南here

剪斷:

// Make a temporary copy of the event to avoid possibility of 
    // a race condition if the last subscriber unsubscribes 
    // immediately after the null check and before the event is raised. 
    EventHandler<CustomEventArgs> handler = RaiseCustomEvent; 
+0

好的,所以這是一個線程安全的問題。但是在MVVM應用程序中,所有這些調用都是由主Dispatcher完成的,所以這不是一個真正的問題,是嗎? – Per 2012-04-03 07:11:45

+0

不一定。是的,視圖將添加/刪除訂閱者在主GUI線程上的綁定。但是您可以在非GUI線程上創建其他模型,該模型訂閱ViewModel屬性上的更改。當然,這可能不是一個很好的設計實踐,也許這些模型應該通過事件聚合器接收通知。 – 2012-05-31 00:31:37

1

這對多線程環境中,在執行之前其它的線程的情況下設置爲null

通過使用本地變量,這是被阻止的,並且分配的委託仍然會被調用。

1

在多線程應用程序中,可能(在第二個示例中)檢查以查看PropertyChanged != null(讓我們假設它不爲null)並實際調用委託之後,您的線程被另一個正在註銷的last來自委託的事件偵聽器。然後,當原始線程恢復並呼叫PropertyChanged(this, new PropertyChangedEventArgs(propertyName));它現在將爲空,並且將拋出NullReferenceException

相關問題