INotifyPropertyChanged – Hardcode This

Background

One thing I always hated about INotifyPropertyChanged is that when it was first introduced, the only way to actually notify a property is by specifying a hard coded value. I call this pattern, The Verbose. It looked something like this:

private int _Integer;
public int Integer
{
    get { return _Integer; }
    set
    {
        if (value != _Integer)
        {
            _Integer = value;
            Notify(@"Integer"); 
        }
    }
}

(Note: Notify is just a helper method to call PropertyChanged(this, new PropertyChangedEventArgs(propertyName));)

The thing that bothered me with this is that pesky Notify(@”Integer”). If you ever refactor that property, you’ll no longer be notified when Integer has been changed unless you go in and manually change the string. There has to be a better way.

After browsing some of the code from this project http://winrtclipboard.codeplex.com/, I found a really neat solution. They kept a Dictionary<string, object> that held all of the property values. This removed the need for the backing property (in this case _Integer). Then they used an Expression Class to pass a lambda in and get the property name. As a result, I dubbed this approach, The Expression and its definition looked like this:

public int Integer
{
    get { return GetValue(() => Integer); }
    set { SetValue(value, () => Integer); }
}

Now you can refactor all you want without ever breaking your notifications because the property name is coming from the Expression you pass into GetValue / SetValue. The one caveat to this implementation is performance. On every call to GetValue or SetValue you’re using reflection to get the member name. So depending on your particular scenario this can either be perfectly fine or a total deal breaker.

For a time, this was all we had . . . and then .NET 4.5 came along and we now have CallerMemberNameAttribute. It’s part of the new Complier Services that ship with VS 2012. The documentation indicates that INotifyPropertyChanged is a intended use for this attribute and they’re right. So if we leverage the Dictionary approach to holding our backing values, we can write properties that look like this:

public int Integer
{
    get { return GetValue<int>(); }
    set { SetValue(value); }
}

I dubbed this approach The Caller. Now that looks very clean. GetValue actually takes an optional parameter with the CallerMemberNameAttribute attached to it. So when we call it without any parameters, the compiler adds the parameter for us and in this case sets it to “Integer”. As it turns out this is faster then the Expression Class method, but using the Dictionary and constantly doing look ups still gives us a performance hit. With the use of a backing object and a helper method though, we can write clean code that performs well and refactors without issue. The result is The Caller Fast and a property definition that looks like this:

private int _Integer;
public int Integer
{
    get { return _Integer; }
    set { SetValue(ref _Integer, value); }
}

SetValue in this case simply compares _Integer & value. If they’re different, _Integer is set to value and Notify is called. Thanks to to CallerMemberNameAttribute we don’t have to pass in what property name just changed.

Performance

After discovering this wonderful attribute, I decided to create a little project that vetted the performance of several of these approaches. I’ve created a little solution that you can download to get all of the source code.

The test consisted of creating several objects, each implemented INotifyPropertyChanged in its own way. The objects are:

  • The Verbose – The initial method I showed. Classic INotifyPropertyChanged.
  • The Expression – The method from WinRTClipboard.CodePlex.com.
  • The Caller – Used CallerMemberAttribute with the dictionary from The Expression.
  • The Caller Fast – A modified version from MSDN to keep our property definitions looking nice and clean.

Each implementation implemented an interface that has 1 property, Integer. I created an array of 100,000 random integers. I then looped over this array for each object and set and get the value of Integer. I wrapped the entire loop in a stopwatch and wrote the results to the console. The results are as follows:

00:00:00.0040000 – The Verbose
00:00:00.0070000 – The Caller Fast
00:00:00.0280000 – The Caller
00:00:00.3070000 – The Expression

As you can see, The Verbose is the fastest. This makes sense as it’s the simplest implementation. The Caller Fast though is a very close second (Remember this a difference of 3 milliseconds for 100000 iterations). When you use a dictionary however, you loose an order of magnitude. The Expression, which uses both reflection and a dictionary to store values is 2 orders of magnitude slower then The Verbose.

Summary

In conclusion, if you can use .NET 4.5 you should really take advantage of CallerMemberNameAttribute. It performs very well and you can refactor your code without worrying about updating literals littered in your code. If you can’t upgrade to .NET 4.5, the Expression method is a very clean solution but shouldn’t be used in situations where you’ll be doing a lot of updates to your properties (i.e. animations).

I hope you found this useful and would love to hear your feedback, so leave us a comment.

Cheers!

//– Joe