Previously I discussed a novel new way of implementing INotifyPropertyChanged based on code I saw during a Build session.
As of yesterday, February 29th, the Visual Studio 11 & .NET 4.5 Betas are out, and included in the .NET 4.5 Beta comes a handy new feature, the CallerMemberName attribute. It is one of three new Caller Information attributes that have been added in this .NET Framework release.
It is joined by the CallerFilePath and CallerLineNumber attributes. These attributes tell the compiler to include information about the caller as a parameter when compiling a method call (there’s no runtime logic involved).
With this new functionality we can code things like logging & tracing routines and INotifyPropertyChanged implementations without having to use string literals, slow reflection code, complex expression tree logic, or code weaving.
Leveraging CallerMemberName, we can now rewrite our previous implementation as the following:
public event PropertyChangedEventHandler PropertyChanged; private void SetProperty<T>(ref T field, T value, [CallerMemberName] string name = "") { if (!EqualityComparer<T>.Default.Equals(field, value)) { field = value; var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); } } } private int unitsInStock; public int UnitsInStock { get { return unitsInStock; } set { SetProperty(ref unitsInStock, value); } }
public event PropertyChangedEventHandler PropertyChanged;
private void SetProperty<T>(ref T field, T value, [CallerMemberName] string name = "")
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
private int unitsInStock;
public int UnitsInStock
{
get { return unitsInStock; }
set
{
SetProperty(ref unitsInStock, value);
}
}
Fast, clean, maintainable, and no outside dependencies!
Last, but not least, for those of you who may prefer a more conventional INotifyPropertyChanged approach, the updated .NET 4.5 MSDN documentation page for INotifyPropertyChanged uses the CallerMemberName attribute in it’s implementation example. (-;




Pingback Dew Drop – March 2, 2012 (#1,278) | Alvin Ashcraft's Morning Dew
Pingback Caller information – New API in .net 4.5 « My musings on .Net Technology
Pingback The Morning Brew - Chris Alcock » The Morning Brew #1058
that is soooo sweet!
Nice work.
Its not a big deal, but is there a reason you create the local variable ‘handler’ rather than just using PropertyChanged directly?
eg : var handler = PropertyChanged;
There is indeed.
If you’re in a multi-threaded environment, calling the event directly can cause an exception to be thrown due to the event being null at the time it’s invoked.
Eric Lippert has a really good write-up on this race condition here: http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx
Thanks. That is very interesting, particularly if writing a threadsafe class. I might have to refactor a few base classes after the enlightenment.
This pitfall, combined with events being a common cause of memory leaks, makes me want to abandon the observer pattern. However, we don’t have a choice with INP of course.
Personally, I prefer to see
public event EventHandler Foo = delegate {};
which obviates the need for the assignment to a local variable. There are just too many issues with compiler and runtime optimisations that might happen, and with dealing with multi-core caching, and perhaps forcing you to (perhaps) use a threading memory barrier to prevent reordering issues on the reads, that I’d rather just have a guaranteed listener.
I
Dave,
The Null Object pattern you’re mentioning is a bit more elegant of a solution to the race condition.
This StackOverflow question discusses that approach a good bit: http://stackoverflow.com/q/170907/53777
While I’m not particularly firm in this opinion, I do feel that handling the race in the common method does a better job of setting up a Pit of Success then assigning an empty delegate does.
In regards to the compiler/runtime messing up the local variable approach, the code I provided (minus the usage of the Caller Info attributes) was written by the creator of the C# language, Anders Hejlsberg, and the approach for dealing with the race condition supported by Eric Lippert, one of the most knowledgeable guys at Microsoft on the guts of .NET and the CLR.
So that said, while it’s not a guarantee, I feel pretty comfortable that the code works for now (you can never guarantee that code will work in the future anyway).
Very neat
Couple of suggestions
Your code will raise the event even if the property has been set to the same value so should check that the value is different in the setter
You can get rid of the threading issues in the event handling using the null pattern
public event PropertyChangedEventHandler PropertyChanged = delegate{};
Richard,
The code does check to see if the value is different and won’t raise the event if the value is the same.
Specifically,
if (!EqualityComparer<T>.Default.Equals(field, value))inSetProperty<T>ensures the values are different before proceeding.That being said, the Null Object pattern you mentioned can also be applied to deal with the race condition.
This StackOverflow has a good discussion of that approach http://stackoverflow.com/q/170907/53777 (largely positive).
Ah sorry Dan – I missed the EqualityComparer
I can still see how people may still favour using a weaving library to reduce the 9 lines of code down to two, but the decision is certainly more marginal with this approach.
I guess the above could be put onto 2 lines (field on one the rest on the second) though, as the property code really is boilerplate. The second line may be considered a little ugly though….
Thanks for sharing!
Rich,
I got into a brief discussion with Simon Cropp about using IL weaving on Twitter after this post.
The implementation above certainly isn’t the end all be all of solutions, just another potential one to be considered.
IL weaving still has a couple of advantages, namely that it’s a bit more flexible then the above approach (it can handle properties that depend on other properties for example).
Pingback INotifyPropertyChanged, The .NET 4.5 Way – Revisited | Dan Rigby
Pingback Implementación de la interfaz INotifyPropertyChanged: presente y el futuro « kashcore
Don’t forget the stack crawl method of seeing what property is calling SetProperty().
For thread-safety, I simply derive viewmodels from DispatcherObject and call VerifyAccess() inside SetProperty(). If you set properties from arbitrary threads, you are taught with pain and it is both immediate and severe. But you know the right thread to switch to first because of the innate Dispatcher property.
Hi Dan,
I was looking for other programming uses of “Caller Info” beside logging & diagnostic purposes – with postsharp around it didn’t seem all that revolutionary. But the INotifyPropertyChanged code you show is such a good example – improving Andres code….
Thanks for this article.