5

When implementing the INotifyPropertyChanged interface in its most basic form, most people seem to implement it like this::

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

My question is: Why the extra assignment of var propertyChanged = PropertyChanged;? Is it just a matter of preference, or is there a good reason for it? Surely the following is just as valid?

public virtual void OnPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
Per
  • 1,074
  • 6
  • 19

3 Answers3

4

The assignment to a temporary variable removes the chance of a race condition between the null check and the last event subscriber, unsubscribing. See the .NET Event Guidelines here.

Snip:

    // 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; 
ahawker
  • 3,306
  • 24
  • 23
  • Ok, so it is a matter of thread safety. But in an MVVM app, all these calls are made from the main Dispatcher, so it's not really an issue, is it? – Per Apr 03 '12 at 07:11
  • Not necessarily. Yes, the views will be adding/removing subscribers for their bindings on the main GUI thread. But you could have other Models, created on a non-GUI thread, that subscribe to changes on a ViewModel's property. Of course, this might not be a great design practice and perhaps those Models should receive notifications via an Event Aggregator. – James Webster May 31 '12 at 00:31
1

It's for multithreaded environments, where some other thread might set the event to null before it is executed.

By using the local variable this is prevented and the assigned delegates will still be called.

BergmannF
  • 9,727
  • 3
  • 37
  • 37
1

In a multithreaded application, it is possible that (in your second example) between checking to see if PropertyChanged != null (let's assume it is not null) and actually calling the delegate, your thread is pre-empted by another that is unregistering the last event listener from the delegate. Then when the original thread resumes and calls PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); it will now be null, and a NullReferenceException will be thrown.

James Webster
  • 4,046
  • 29
  • 41