INotifyPropertyChanged implementations: An Overview

Summary

One of the cornerstones of MVVM is the INotifyPropertyChanged interface. This post describes several implementations that have been used/proposed over time.

Table of contents

Introduction

One of the cornerstones of MVVM is the INotifyPropertyChanged interface. This post describes several implementations that have been used/proposed over time.

The basic ingredient of each INotifyPropertyChanged implementation is the declaration of the PropertyChanged event, and a function to raise this event. We will use the following:

public class BindableObject
{
	public event PropertyChangedEventHandler PropertyChanged;
 
	protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler == null || String.IsNullOrWhiteSpace(propertyName))
            {
                return;
            }
 
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
}

The challenge in implementing the interface is to get the proper value for the propertyName argument of the OnPropertyChanged in a re-factor-friendly way.

Defacto standard

The typical defacto standard way of implementing a property is the following:

private string useString;
 
public string UseString
{
	get
	{
		return this.useString;
	}
	set
	{
		if (Object.Equals(this.useString, value))
		{
			return;
		}
		this.useString = value;
 
		OnPropertyChanged("UseString");
	}
}

The code in the setter is sometimes re-factored using a generic function like this:

protected bool SetValue<T>(ref T property, T value, string propertyName)
{
	if (Object.Equals(property, value))
	{
		return false;
	}
	property = value;
 
	OnPropertyChanged(propertyName);
 
	return true;
}

to this:

public string UseString
{
	get
	{
		return this.useString;
	}
	set
	{
		SetValue(ref this.useString, value, "UseString");
	}
}

This solution is not re-factor friendly: when you change the name of the property, you also have to change manually the string containing the name of the property. Failing to do this, does not lead to compiler errors, but will certainly lead to bugs that are difficult to track down. To tackle this problem the propertyName parameter of the function OnPropertyChanged Josh Smith proposed using the following function:

[Conditional("DEBUG")]
private void VerifyProperty(string propertyName)
{
	Type type = this.GetType();
 
	// Look for a public property with the specified name.
	PropertyInfo propInfo = type.GetProperty(propertyName);
 
	Debug.Assert(propInfo != null, string.Format(CultureInfo.InvariantCulture, "{0} is not a property of {1}", propertyName, type.FullName));
}

This leads to the following implementation of OnPropertyChanged:

protected void OnPropertyChanged(string propertyName)
{
	VerifyProperty(propertyName);
 
	PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler == null || String.IsNullOrWhiteSpace(propertyName))
        {
        	return;
	}
 
	handler(this, new PropertyChangedEventArgs(propertyName));
}

This approach will not lead to compile-time errors when the string containing the property name does not match the actual property name, but it will raise an assertion error in debug builds when OnPropertyChanged is called with non existent property names. However, this approach fails when the a wrong name is used of a property that does exist in the class. For example:

private string property1;
private string property2;
 
public string Property1
{
	get { return this.property1; }
	set { SetValue(ref this.property1, value, "Property1"); }
}
 
public string Property2
{
	get { return this.property2; }
	set { SetValue(ref this.property2, value, "Property1"); }
}

When copy/paste programming is used, this is likely to happen.

Using Lambda Expressions and Expression Trees

Refactor friendly INotifyPropertyChanged implementations like this use Lambda Expressions and Expression Trees to determine the property name using a function like this:

public static string GetPropertyNameFromExpression<T>(Expression<Func<T>> property)
{
	var lambda = (LambdaExpression)property;
	MemberExpression memberExpression;
 
	if (lambda.Body is UnaryExpression)
	{
		var unaryExpression = (UnaryExpression)lambda.Body;
                memberExpression = (MemberExpression)unaryExpression.Operand;
	}
	else
	{
		memberExpression = (MemberExpression)lambda.Body;
	}
 
	return memberExpression.Member.Name;
}

with which the following implementation of OnPropertyChanged can be defined:

protected void OnPropertyChanged<T>(Expression<Func<T>> property)
{
	OnPropertyChanged(GetPropertyNameFromExpression(property));
}

Now we can implement a property as follows:

private string useDelegate;
 
public string UseDelegate
{
	get
	{
		return this.useDelegate;
	}
	set
	{
		if (Object.Equals(this.useDelegate, value))
		{
			return;
		}
		this.useDelegate = value;
 
		OnPropertyChanged(() => UseDelegate);
	}
}

or with the following definition of SetValue

protected bool SetValue<T>(ref T property, T value, Expression<Func<T>> propertyDelegate)
{
	if (Object.Equals(property, value))
	{
		return false;
	}
	property = value;
 
	OnPropertyChanged(propertyDelegate);
 
	return true;
}

we can rewrite the property definition as follows:

public string UseDelegate
{
	get
	{
		return this.useDelegate;
	}
	set
	{
		SetValue(ref this.useDelegate, value, () => UseDelegate);
	}
}

The upside of this approach is, that it is re-factor friendly: whenever the name of the property is re-factored using a re-factor-tool, the delegate is re-factored too and the correct property name is used in the PropertyChanged event. Another advantage is that misspellings lead to compiler errors, so there is no need for the VerifyProperty function. On the downside: due to the use of reflection, you can experience a performance hit. Furthermore: this approach is also vulnerable to bugs introduced by copy/paste programming like this:

private string property1;
private string property2;
 
public string Property1
{
	get { return this.property1; }
	set { SetValue(ref this.property1, value, () => Property1); }
}
 
public string Property2
{
	get { return this.property2; }
	set { SetValue(ref this.property2, value, () => Property1); }
}

On a personal note: I do not like the way this approach looks in code. It has some code smell about it.

Using MethodBase.GetCurrentMethod()

Karl Shifflett took another road in this article: he proposed to get the property name from using MethodBase.GetCurrentMethod(). This leads to the following implementation of a property:

public string UseMethodBase
{
	get
	{
		return this.useString;
	}
	set
	{
		SetValue(ref this.useString, value, MethodBase.GetCurrentMethod().Name.Remove(0,4));
	}
}

This solution works quite well, although in his article Karl states:
There could be issues with reliability of reflection for production environment where assemblies can be obfuscated, delayed signed etc.
So probably when using this method, it is wise to leave the VerifyProperty function in place.

Because this approach is based upon reflection too, a performance hit is to be expected. Furthermore it is impossible to re-factor the call to MethodBase.GetCurrentMethod() into a helper function, so when using this approach you are stuck using the call to MethodBase.GetCurrentMethod().Name.Remove(0,4) in every property setter.

Using StackTrace

Important note: the following approach will not work in optimized release builds, so this approach is probably not suited for production code. This approach is included because it shows a very clean interface.

Using the StackTrace class we could determine the name of the property setter using the following function:

private static string GetPropertyNameFromStackTrace()
{
	StackTrace stackTrace = new StackTrace();           // get call stack
        StackFrame[] stackFrames = stackTrace.GetFrames();  // get method calls (frames)
 
	foreach (StackFrame stackFrame in stackFrames)
        {
		string name = stackFrame.GetMethod().Name;
 
		if (name.StartsWith("set_", StringComparison.Ordinal))
                {
			return name.Substring(4);
                }
	}
 
	string s = "";
	foreach (StackFrame stackFrame in stackFrames)
	{
		s += "   " + stackFrame.GetMethod().Name + Environment.NewLine;
	}
	throw new Exception("Could not determine property name. StackTrace:\n" + s);
}

With this we could create the following implementation of OnPropertyChanged:

protected void OnPropertyChanged()
{
	OnPropertyChanged(GetPropertyNameFromStackTrace());
}

The property implementation would become

private string useStackTrace;
 
public string UseStackTrace
{
	get
	{
		return this.useStackTrace;
	}
	set
	{
		if (Object.Equals(this.useStackTrace, value))
		{
			return;
		}
		this.useStackTrace = value;
 
		OnPropertyChanged();
	}
}

or with the following definition of SetValue

protected bool SetValue<T>(ref T property, T value)
{
	if (Object.Equals(property, value))
	{
		return false;
	}
	property = value;
 
	OnPropertyChanged();
 
	return true;
}

we can rewrite the property definition as follows:

public string UseStackTrace
{
	get
	{
		return this.useStackTrace;
	}
	set
	{
		SetValue(ref this.useStackTrace, value);
	}
}

From a development point of view, this is a very neat solution. But unfortunately the documentation of StackTrace states that Stacktrace might not report as many method calls as expected, due to code transformations that occur during optimization. For this approach to work at least the following must be true:

  • The name of the property setter must not be mangled for instance by by obfuscation
  • The setter must not be in-lined

According to this article written in 2004, we can prevent in-lining of the setter by applying the MethodImpl attribute like this:

public string UseStackTrace
{
	get
	{
		return this.useStackTrace;
	}
	[MethodImpl(MethodImplOptions.NoInlining)]
	set
	{
		SetValue(ref this.useStackTrace, value);
	}
}

Unfortunately having to apply this attribute to every setter takes away some of the neatness of this solution.

Performance comparison

Below is the output of a performance test run. The run is made with an optimized release build a release build, without any .pdb files, running from the command line running on Windows 7 in a virtual machine running on Windows XP. The PropertyChanged event handler contained some mathematical calculations to a simulate the actions that are usually performed in the event handler. The source code of the test can be found here.

1     times using                 UseString => 1,9531 ms
1     times using         UseStringVerified => 0 ms
1     times using             UseMethodBase => 0,9766 ms
1     times using     UseMethodBaseVerified => 0 ms
1     times using             UseExpression => 0 ms
1     times using     UseExpressionVerified => 0 ms
1     times using             UseStackTrace => 0 ms
1     times using     UseStackTraceVerified => 0 ms
 
501   times using                 UseString => 83,9844 ms
501   times using         UseStringVerified => 88,8672 ms
501   times using             UseMethodBase => 92,7734 ms
501   times using     UseMethodBaseVerified => 85,9375 ms
501   times using             UseExpression => 80,0781 ms
501   times using     UseExpressionVerified => 78,125 ms
501   times using             UseStackTrace => 92,7735 ms
501   times using     UseStackTraceVerified => 88,8671 ms
 
1001  times using                 UseString => 155,2734 ms
1001  times using         UseStringVerified => 153,3203 ms
1001  times using             UseMethodBase => 157,2265 ms
1001  times using     UseMethodBaseVerified => 157,2266 ms
1001  times using             UseExpression => 160,1563 ms
1001  times using     UseExpressionVerified => 164,0625 ms
1001  times using             UseStackTrace => 175,7812 ms
1001  times using     UseStackTraceVerified => 172,8515 ms
 
1501  times using                 UseString => 226,5625 ms
1501  times using         UseStringVerified => 227,5391 ms
1501  times using             UseMethodBase => 246,0938 ms
1501  times using     UseMethodBaseVerified => 248,0469 ms
1501  times using             UseExpression => 264,6485 ms
1501  times using     UseExpressionVerified => 246,0937 ms
1501  times using             UseStackTrace => 258,7891 ms
1501  times using     UseStackTraceVerified => 262,6953 ms
 
2001  times using                 UseString => 299,8047 ms
2001  times using         UseStringVerified => 296,875 ms
2001  times using             UseMethodBase => 339,8437 ms
2001  times using     UseMethodBaseVerified => 355,4688 ms
2001  times using             UseExpression => 300,7812 ms
2001  times using     UseExpressionVerified => 325,1953 ms
2001  times using             UseStackTrace => 343,75 ms
2001  times using     UseStackTraceVerified => 388,6718 ms

Although we can conclude that using reflection incurs a performance hit, this hit is not as dramatic as expected: much less than 0.1 ms per event. This difference will not be noticeable for normal, Silverlight (business) applications, in which normally two to ten property changed events are raised. On the other hand, I agree with Karl Shifflett: If you have an application that has 100′s of events per second or more like real-time graphing applications, I would not use this method for performance reasons. Instead, go with string constants for the property names or double quoted strings if you like that better.

Other strategies

MSIL weaving

Justin Angel has created a solution that implements INotifyPropertyChanged by injecting the necessary code in the property setters using Mono.Cecil as well as PostSharp 1.5. Gael Fraiteur has created a PostSharp 2.0 version. Simon Cropp created NotifyPropertyWeaver based on the Mono.Cecil implementation of Justin Angel.

Using Proxy objects

Einar Ingebrigtsen has proposed an implementation based on proxy objects. The downside of using this approach is that the classes cannot be instantiated using the keyword new anymore.

Ray Houston used a similar approach here and Jonas Follesø did something similar too.

Using Aspect Oriented Programming

Sacha Barber has implemented the INotifyPropertyChanged interface using 4 different Aspect Oriented Programming techniques which can be found in this well written article.

Additional reading

The following links may be helpful:

Source download

The sources for this article can be downloaded here.

19 Responses to “INotifyPropertyChanged implementations: An Overview”

  1. Cool INotifyPropertyChanged implementation said:

    Jun 27, 10 at 1:08 am

    [...] Next, I would like to ask if there really are performance issues here!? Let’s take a pretty common scenario. The user clicks a button, a command is called, the command executes some code that changes 2 properties that cause 2 property changed notifications. Those two notifications causes the UI to render something else on the screen. So with all of this happening (code executing, UI re-rendering and so on), will the property notification be the biggest problem? I actually don’t think so, I think that part of it is so small that you can ignore it. For the performance for different notification implementations, have a look here: http://www.pochet.net/blog/2010/06/25/inotifypropertychanged-implementations-an-overview/ [...]

  2. Andy French said:

    Jun 27, 10 at 11:14 am

    Great post on an issue that has been bugging me since I first started looking at Silverlight.

    I am a relative newbie to Silverlight (although not to software development) but the first time I saw how INotifyPropertyChanged was being implemented I thought this was a classic “cross cutting concern” and should be ripe for an Aspect Oriented Programming (AOP) implementation.

    Having to pollute your properties with additional calls to OnPropertyChanged(), SetValue() or whatever just smells bad. All you should be concerned with is identify thorough configuration (e.g. attributes) what properties need to participate in INotifyPropertyChanged. Then some type of interceptor should be in place ready to be invoked when the property is changed and which deals with the whole property changed notification issue.

    A quick web search indicates that a number of people have had similar ideas. I haven’t had a chance to try this myself yet but I’d be interested in anyone else’s experience.

  3. Michael L Perry said:

    Jun 29, 10 at 2:36 pm

    The hardest problem with INotifyPropertyChanged is often overlooked: dependency management. When one property is changed, all of its dependent properties need to fire as well. You can find my solution to that problem at the link above. What do you usually do about that?

  4. Sergey Lutay's Blog | Sergey Lutay's Blog - Варианты реализации INotifyPropertyChanged said:

    Jul 01, 10 at 12:04 am

    [...] INotifyPropertyChanged implementations: An Overview [...]

  5. Emiel said:

    Jul 02, 10 at 5:25 pm

    @Michael L Perry: I have written a blog about this here. I am curious about your reaction…

  6. Simon said:

    Jul 10, 10 at 4:33 am

    Emiel

    I would be interested to get your feedback on this

    http://code.google.com/p/notifypropertyweaver/

  7. Emiel said:

    Jul 12, 10 at 11:56 am

    @Simon: as far as I can tell this is a standard implementation implemented using the techniques of Justin Angel.

    It is a nice approach, especially if it could be extended to use the techniques described here.

    I have added a link to this solution in the blog.

  8. Windows Phone 7 ListBox Pagination with MVVMLight & ApplicationBar « Indyfromoz’s Weblog said:

    Aug 30, 10 at 1:37 pm

    [...] INotifyPropertyChanged Overview [...]

  9. Eric Willeke said:

    Oct 18, 10 at 5:45 pm

    Great summary of the approaches, the Lambda/Expression tree approach seems to have the most promise.

    People mostly look at this in the context of yielding properties for binding in XAML out of the ViewModel. There are also quite a few other uses in more complicated applications where you want to bind to a property changing on the Model (from the ViewModel) in order to know _when_ to update your properties.

    In this case, the subscription side of the question becomes much more interesting, especially when something like the Prism EventAggregator is involved. The “refactor friendly” aspect becomes much much more important in those cases!

  10. nRoute – Les bases de nRoute et le MVVM at John's Technical Weblog said:

    Oct 20, 10 at 12:27 am

    [...] [...]

  11. nRoute – MVVM basics at John’s Technical Weblog said:

    Oct 24, 10 at 4:35 pm

    [...] http://www.pochet.net/blog/2010/06/25/inotifypropertychanged-implementations-an-overview/. [...]

  12. Pavel Savara said:

    Mar 26, 11 at 9:28 pm

    Hi everyone,
    stack walk is slow and lambda expression is even slower. We have solution similar to well known lambda expression but almost as fast as string literal. See
    http://zamboch.blogspot.com/2011/03/raising-property-changed-fast-and-safe.html

  13. Emiel said:

    Mar 29, 11 at 10:51 pm

    For what I make of it, you basically take one ot the techniques described in this post and than cache the result in order to improve the performance. Am I correct?

  14. nRoute – MVVM basics at John's technical weblog said:

    Apr 03, 11 at 5:51 pm

    [...] http://www.pochet.net/blog/2010/06/25/inotifypropertychanged-implementations-an-overview/. [...]

  15. Sergey said:

    Oct 28, 11 at 9:09 am

    The Speed test is not correct. It performs 4000 System.Math operations in a PropertyChanged handler which dwarfs any speed differences in the methods tested. With an empty handler, this yields:

    100000 times using UseString => 5.0003 ms
    100000 times using UseStringVerified => 37.0021 ms
    100000 times using UseMethodBase => 258.0148 ms
    100000 times using UseMethodBaseVerified => 344.0197 ms
    100000 times using UseExpression => 629.036 ms
    100000 times using UseExpressionVerified => 629.0359 ms
    100000 times using UseStackTrace => 1803.1031 ms
    100000 times using UseStackTraceVerified => 1931.1105 ms

    There is also CallerMemberName attribute in the upcoming C# 5 which tells the compiler to put the caller member name in the string parameter on which it is applied.

  16. ibratoev said:

    Dec 07, 11 at 10:51 am

    Nice post :)
    Also consider using System.Diagnostics.Stopwatch. Results are a bit more precise. On my machine:
    1 times using UseString => 299 ticks
    1 times using UseStringVerified => 297 ticks
    1 times using UseMethodBase => 305 ticks
    1 times using UseMethodBaseVerified => 311 ticks
    1 times using UseExpression => 384 ticks
    1 times using UseExpressionVerified => 325 ticks
    1 times using UseStackTrace => 352 ticks
    1 times using UseStackTraceVerified => 339 ticks

    501 times using UseString => 150202 ticks
    501 times using UseStringVerified => 148810 ticks
    501 times using UseMethodBase => 150633 ticks
    501 times using UseMethodBaseVerified => 154308 ticks
    501 times using UseExpression => 156054 ticks
    501 times using UseExpressionVerified => 154616 ticks
    501 times using UseStackTrace => 161979 ticks
    501 times using UseStackTraceVerified => 164815 ticks

    1001 times using UseString => 293697 ticks
    1001 times using UseStringVerified => 294834 ticks
    1001 times using UseMethodBase => 301462 ticks
    1001 times using UseMethodBaseVerified => 305095 ticks
    1001 times using UseExpression => 307167 ticks
    1001 times using UseExpressionVerified => 306694 ticks
    1001 times using UseStackTrace => 323592 ticks
    1001 times using UseStackTraceVerified => 325578 ticks

    1501 times using UseString => 442076 ticks
    1501 times using UseStringVerified => 445532 ticks
    1501 times using UseMethodBase => 448154 ticks
    1501 times using UseMethodBaseVerified => 455503 ticks
    1501 times using UseExpression => 461096 ticks
    1501 times using UseExpressionVerified => 459862 ticks
    1501 times using UseStackTrace => 490830 ticks
    1501 times using UseStackTraceVerified => 488677 ticks

    2001 times using UseString => 589203 ticks
    2001 times using UseStringVerified => 593140 ticks
    2001 times using UseMethodBase => 605011 ticks
    2001 times using UseMethodBaseVerified => 606303 ticks
    2001 times using UseExpression => 614216 ticks
    2001 times using UseExpressionVerified => 615003 ticks
    2001 times using UseStackTrace => 654534 ticks
    2001 times using UseStackTraceVerified => 648982 ticks

  17. ibratoev said:

    Dec 07, 11 at 11:19 am

    And BTW, simply caching the invocation expression will result in 10 time performance improvement (measured without the Math operation in the event handler).
    Example:

    private Expression<Func> useExpressionPropertyChanged;

    public string UseExpression
    {
    get
    {
    return this.useExpression;
    }
    set
    {
    this.useExpression = value;

    if (useExpressionPropertyChanged == null)
    {
    useExpressionPropertyChanged = () => UseExpression;
    }

    this.OnPropertyChanged(useExpressionPropertyChanged);
    }
    }

  18. On developing Pochet.NET» Blog Archive » INotifyPropertyChanged: automatic dependent property and nested object support said:

    Jul 09, 12 at 10:58 am

    [...] stated by Michael L Perry in a comment on my blog INotifyPropertyChanged implementations: An [...]

  19. Gerard said:

    Oct 12, 12 at 4:40 pm

    You could also use the simple defacto standard and then make a custom tool that checks and refactors the code file according to the defacto standard. This tool could be a pre-build task,also on the build server.