Overview
I have never been really thrilled with having to write code to implement the INotifyPropertyChanged
interface. Part of the reason is that it does not feel right having to use string
s when triggering the PropertyChanged
event, and then there is all the code that is required. Originally there had to be a backing field for all properties, and then Microsoft made a big step forward and made properties much simpler by not requiring the defining of a backing field. With WPF, it was two (maybe more) steps back. Anything to simplify simple properties for WPF/Silverlight binding is a step forward. The best option possible would be to call a method in the property that implements the required code, but this requires some tricks.
Implementation of INotifyPropertyChanged
The MSDN recommended implementation for INotifyPropertyChanged
(How to: Implement the INotifyPropertyChanged
Interface) is similar to the following:
class MsdnVersionExample : INotifyPropertyChanged
{
private int _variable;
public int Variable
{
get { return this._variable; }
set
{
if (value != this._variable)
{
this._variable = value;
NotifyPropertyChanged("Variable");
}
}
}
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
This code implements most of what should be in the property used for binding but it is a lot of code and this has to be done for each property, and it is actually missing a feature it should have.
In Anders Hejlsberg talk Future directions for C# and Visual Basic, I noticed that he did something very different:
class AndersVersionExample : INotifyPropertyChanged
{
private int _variable;
public int Variable
{
get { return this._variable; }
set
{
SetProperty(ref _variable, value, "Variable");
}
}
private void SetProperty<T>(ref T field, T value, string propertyName)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
This does a great job of cleaning up the actual property itself, meaning that everything is cleaner. What allows this to work is the EquityComparer<T>.Default
, which exposes the Equals
method. Also note the actual handling of the event where there a “handler” used to save the event information before firing an event (which can prevent a race condition) is internally the Microsoft preferred method.
Now looking that the Ander’s implementation and the MSDN implementation, it can immediately be seen that the MSDN is missing the assigning of the PropertyChanged
to a variable before firing the event. This is to prevent a race condition, and is internally preferred practice within Microsoft Corporation. Many people will even use the simpler implementation than the MSDN, which is not to check if the value has been changed before changing the value and firing the PropertyChanged
event. Thus the code that should be implemented for each simple property for binding is quite a bit, and repeating the code becomes a maintenance issue, and all this extra code clouds the understanding of what the application is doing.
In my group, we have been using something different, which has the advantage of eliminating the magic string
, which is the name of the property:
class OurVersionExample : INotifyPropertyChanged
{
private int _variable;
public int Variable
{
get { return this._variable; }
set
{
if (value != this._variable)
{
this._variable = value;
NotifyPropertyChanged(GetPropertyName(() => Variable));
}
}
}
public static string GetPropertyName<T>(Expression<Func<T>> property)
{
var memberExpression = (MemberExpression)((lambda.Body is UnaryExpression)
? ((UnaryExpression)lambda.Body).Operand : lambda.Body);
Debug.Assert(memberExpression != null);
return memberExpression.Member.Name;
}
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Now this is very nice since when the variable name is changed using refactoring, the value used in the property changed is also changed, however, there is going to be a performance impact, which I shall get into later. (I did make some changes from what we were originally using, inserting the Debug.Assert
instead of doing a check since this will not be in the production code, and there should not be a case where memberExpression
is null
unless there is a fairly obvious error in the property code. I also cleaned up a couple of other issues.)
If the “Expression<Func<T>>
” is confusing, I have to agree it is. What the Expression does is that it gives access to the anonymous method. This is used because it provides information about the lambda expression, which would not be available if there was just the lambda expression in the argument. It is possible to create the lambda expression using the compile statement (in this case would compile to Func<T>
):
Func<T> _lambda = `_expression.Compile ();
Then this function (Func<T>
) could just be executed:
var value = _lambda();
I believe that the “UnaryExpression
” is to handle the case the programmer places parenthesis around the variable, so could be dropped. This is not code that I wrote, and know that there have been other cases where there have been issues.
Now I like what Anders did, and I like the way our group does it. I do know that the actual handling of the event where there a “handler” is used to save the event information before firing an event (which can prevent a race condition) is the preferred method, why not combine the two:
class ModifiedAndersVersionExample : INotifyPropertyChanged
{
private int _variable;
public int Variable
{
get { return this._variable; }
set
{
SetProperty(ref _variable, value, () => Variable);
}
}
private void SetProperty<T>(ref T field, T value, Expression<Func<T>> property)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
NotifyPropertyChanged (property);
}
}
public void NotifyPropertyChanged<T>(Expression<Func<T>> property)
{
var handler = PropertyChanged;
if (handler != null)
{
var memberExpression = (MemberExpression)((lambda.Body is UnaryExpression)
? ((UnaryExpression)lambda.Body).Operand : lambda.Body);
Debug.Assert(memberExpression != null);
handler(this, new PropertyChangedEventArgs(memberExpression.Member.Name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
You will notice that I still have the NotifyPropertyChanged
method and also Ander’s SetProperty
method, however the SetProperty
method now calls the NotifyPropertyChanged
method. I use two methods because there are many times that the PropertyChanged
event needs to be fired, but the value is already correct (could be that some equation or a Linq statement is used to determine the right value).
A final test also includes a call to MethodBase.GetCurrentMethod()
to get the property name so that the straight Anders' method can be used (This test was added because of a comment from Hanzie53). The performance actually looks good compared to the lambda methods, but what cannot be seen in the results is the initialization cost. It has two disadvantages: it makes the call more complex, and MethodBase.GetCurrentMethod()
cannot be used outside of the property. The actual test is a little bastardized because I am not calling MethodBase.GetCurrentMethod()
from a property.
Another comment lead me to also test saving the name in a dictionary, but the cost the checking and lookup appeared to have similar performance cost, and I did not think it was worth leaving in the test.
Results
Obviously making the properties simpler using a call to a method has the advantages of code reuse, but at what cost. Ander’s method does not appear to have too much of a performance hit, but how much, and how much penalty will there be passing a lambda expression which will allow the name of the property to be determined.
The application included with this article is basically a test of the four implementations for INotifyPropertyChanged
:
- Basic MSDN implementation
- The implementation my group has been using
- The implementation from the Anders Hejlsberg talk
- The implementation combining the Anders’ version and the one we have been using
- The implementation combining the Anders’ version with
MethodBase.GetCurrentMethod()
I do several runs, which include:
- Initial run, which will get everything complied and in memory (Note: There is a significant difference when running 1000 iterations instead of 10,000)
- A second run where everything should be compiled and in memory
- A run where an empty event handler is triggered
- A run where there is binding to the
Text
property of a TextBlock
on a WPF form.
A sample run produces the following results:
First Run
Count of number of iterations: 10000
Time for MSDN Implementation = 581 ticks
Time for our current implementation = 119532 ticks
Time for Anders implementation = 815 ticks
Time for combined implementation = 117971 ticks
Time for combined implementation = 119639 ticks
Time using reflection GetCurrentMethod = 61407 ticks
Second Run
Count of number of iterations: 10000
Time for MSDN Implementation = 560 ticks
Time for our current implementation = 116366 ticks
Time for Anders implementation = 1334 ticks
Time for combined implementation = 120099 ticks
Time for combined implementation = 119186 ticks
Time using reflection GetCurrentMethod = 61814 ticks
Run with Property Changed event
Count of number of iterations: 10000
Time for MSDN Implementation = 888 ticks
Time for our current implementation = 117229 ticks
Time for Anders implementation = 1211 ticks
Time for combined implementation = 129511 ticks
Time for combined implementation = 123790 ticks
Time using reflection GetCurrentMethod = 61666 ticks
Run with Binding
Count of number of iterations: 10000
Time for MSDN Implementation = 183643 ticks
Time for our current implementation = 427613 ticks
Time for Anders implementation = 190121 ticks
Time for combined implementation = 427392 ticks
Time for combined implementation = 425799 ticks
Time using reflection GetCurrentMethod = 346575 ticks
As can be seen from the results, the impact of using implementation from Anders’ talk is minimal; significantly less than having to handle an empty event. Doing the determination of the Name using a lambda expression has a very high overhead, on the order of the cost for binding. Using the MethodBase.GetCurrentMethod()
to get the name gives a significant performance improvement over using a lambda expression. (Note: This is not a realistic situation, and it may be that the real cost of binding could be much higher since the framework could be eliminating redundant events). The image below is the running of the example included with this article, only run with only 1000 iterations instead of 10,000. It can be seen that the time required for 1000 iterations it is bit more than 1/10th the time of 10,000.

Implementation
My group does not actually put this INotifyPropertyChanged
code in every ViewModel
, instead there is an abstract
class that contains the INotifyPropertyChanged
code, and all ViewModels
inherit from this abstract
class.
C# 5.0
smolesen pointed out that C# 5.0 may give us another approach using Caller Info Attributes. This will allow the Anders' implementation to be modified as follows:
class AndersVersionExample : INotifyPropertyChanged
{
private int _variable;
public int Variable
{
get { return this._variable; }
set
{
SetProperty(ref _variable, value);
}
}
private void SetProperty<T>(ref T field, T value,
[CallerMemberName] string propertyName = "")
{
if (!EqualityComparer<t />.Default.Equals(field, value))
{
field = value;
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Conclusion
After my investigation, we are definitely going to apply the Anders’ ideas into our code, and we are also going to investigate whether elimination of the determination of the property name from a lambda expression will give us an appreciable performance gain—my initial impression is that the maintenance improvement of using the lambda expression will be worth the performance penalty. However, in a grid with many controls, it may be that there will be an appreciable performance gain. Therefore, we will probably use the Anders’ implementation with and without the lambda expression.
Maybe with Rosyln properties used for binding can be made simpler, with just an attribute, in the mean time we can learn from the implementation in Anders’ talk.
Do look at some of the responses I got from other users because they may include ideas that you may prefer over what I have presented in the article. I may not have included them in the article because I did not think that they was a significant improvement in maintainability from what I presented, however opinions differ and the approaches do have merit.
History
- 15th February, 2012: Initial version
- 21st February, 2012: Update includes changes due to comments from other members, and some code fixes
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last eight years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with BioNano Genomics in San Diego, CA redesigning their UI for their camera system. he can be reached at qck1@hotmail.com.