Using the New Caller Information Attributes for Reliable Property Change Notifications

As anyone who has implemented the INotifyPropertyChanged interface knows, the fact that the PropertyChangedEventArgs takes a property name as a string means that you are one fat-fingered mistake away from a bug that can sometimes be difficult to track down.  If the property name supplied in the string doesn’t match the actual property name, the data binding (or other operations) that relies on this interface doesn’t work properly.

   1: public Int32 MyProperty

   2: {

   3:     get { return _myProperty; }

   4:     set

   5:     {

   6:         if (_myProperty != value)

   7:         {

   8:             _myProperty = value;

   9:             OnPropertyChanged("MyProperty");

  10:         }

  11:     }

  12: }

Lambda expressions and Expression Trees in .Net 3 brought a solution to the problem, where the compile-time checking could help ensure that a correct value was provided.  I blogged about this back in 2010 (https://blog.dotnetgator.com/2010/06/21/finding-binding-trouble/), and even cited my (then-future) coworker Jeremy Likness’s treatment of the same topic (http://csharperimage.jeremylikness.com/2010/06/tips-and-tricks-for-inotifypropertychan.html).

   1: public Int32 MyProperty

   2: {

   3:     get { return _myProperty; }

   4:     set

   5:     {

   6:         if (_myProperty != value)

   7:         {

   8:             _myProperty = value;

   9:             OnPropertyChanged(() => MyProperty);

  10:         }

  11:     }

  12: }

Now there’s a new feature in .Net 4.5 that provides yet another opportunity to ensure that INotifyPropertyChanged is implemented correctly – possibly in a simpler fashion than ever before, and with better performance than the Expression Tree/Lambda expression approach.

.Net 4.5 includes 3 new “Caller Information” attributes  – CallerFilePathAttribute, CallerLineNumberAttribute, and CallerMemberNameAttribute.  These three attributes are scoped to individual method parameters, and when used, they apply the indicated value from the CALLING METHOD to the called method’s attributed parameter at run time.  In our case, we’re interested in the CallerMemberName attribute, which we can use to automatically retrieve the property that is trying to raise the property change notification:

   1: private void OnPropertyChanged([CallerMemberName] String caller = null)

   2: {

   3:     var handler = PropertyChanged;

   4:     if (handler != null)

   5:     {

   6:         handler(this, new PropertyChangedEventArgs(caller));

   7:     }

   8: }

Note that the Caller Information attributes require a default value be supplied.

This reduces the overhead of a property in the class that provides this method to the following:

   1: public Int32 MyProperty

   2: {

   3:     get { return _myProperty; }

   4:     set

   5:     {

   6:         if (_myProperty != value)

   7:         {

   8:             _myProperty = value;

   9:             OnPropertyChanged();

  10:         }

  11:     }

  12: }

Of course, one important question is how does this method perform in comparison to either just providing a string, or using the Lambda/Expression Tree approach?  In my tests with iterations of between 1,000-500,000 property changes I saw between ~10-30% performance improvement over the Lambda/Expression Tree approach, and performance between ~20-30% lower than using a directly supplied string.

Note that the latest version of the MSDN documentation illustrating the implementation of the INotifyPropertyChanged interface (as of this writing) show the use of the CallerMemberName attribute – http://msdn.microsoft.com/en-us/library/ms229614(v=vs.110).aspx

Advertisements

One thought on “Using the New Caller Information Attributes for Reliable Property Change Notifications

  1. For each property, you should just define a field:

    private static readonly PropertyChangedEventArgs MyProperty_PropertyChangedEventArgs = new PropertyChangedEventArgs(“MyProperty”);

    .. and use it when raising events:

    OnPropertyChanged(MyProperty_PropertyChangedEventArgs);

    This is almost typo-proof, and is also perfomant, since no throw-away object is created every time value changes.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s