2012-04-03 14 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 –

答えて

4

一時変数への代入はnullをチェックし、最後のイベントの加入、退会の間で競合状態の可能性を除去します。 .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アプリケーションでは、これらの呼び出しはすべてメインディスパッチャから行われるため、実際問題ではありません。 – Per

+0

必ずしもそうではありません。はい、ビューはメインGUIスレッド上のバインディングに対してサブスクライバを追加/削除することになります。しかし、GUI以外のスレッドで作成され、ViewModelのプロパティの変更をサブスクライブする他のモデルを持つことができます。もちろん、これは素晴らしい設計手法ではないかもしれません。おそらくそれらのモデルはEvent Aggregatorを介して通知を受け取るべきです。 –

1

それは、それが実行される前に、いくつかの他のスレッドがnullにイベントを設定するかもしれませんマルチスレッド環境のためです。

ローカル変数を使用することによって、これは防止され、割り当てられたデリゲートは依然として呼び出されます。

1

マルチスレッドアプリケーションでは、PropertyChanged != null(nullではないものと仮定します)をチェックして実際にデリゲートを呼び出すかどうかをチェックする(2番目の例では)、スレッドは未登録のスレッドによってプリエンプトされる可能性があります最後デリゲートからのイベントリスナー。その後、元のスレッドが再開し、PropertyChanged(this, new PropertyChangedEventArgs(propertyName));を呼び出すとnullになり、NullReferenceExceptionがスローされます。