RSS
 

Raising the right PropertyChanged with C# 5′s Caller Info Attributes

21 Sep
Implementing INotifyPropertyChanged typically requires the use of magic strings, and I've never been happy with the various workarounds available. They either affect performance or require a lot of extra developer ceremony (which is no good in big teams). I'd always been hoping that C# would introduce something similar to the "typeof" operator that would help you get the name of the current property (or method) without having to use any slow reflection. Before the "//BUILD/" conference, I had given up on C# 5 bringing in anything useful here. But then I was reading Colin Jack's summary of the //BUILD/ talk on Future directions for C# and Visual Basic, and was particularly interested by the new Caller Info Attributes feature of C# 5. This feature is not in the CTP of VS11 yet, so I can't test it, but I expect you'll be able to write the following RaisePropertyChanged method:
protected void RaisePropertyChanged([CallerMemberName] string member = "")
{
    var copy = PropertyChanged;
    if(copy != null)
    {
        copy(new PropertyChangedEventArgs(this, member));
    }
}
and now when you call this method from a property setter, leaving out the optional parameter:
public string UserName
{
    get
    {
        return _userName;
    }
    set
    {
        _userName=value;
        RaisePropertyChanged();
    }
}
the compiler will fill out the parameter for you, passing "UserName" to the RaisePropertyChanged method. What I like about this is that the compiler is creating the magic string for you on every compile - so when you rename your property, the string is automatically kept in sync. This is the best of both worlds, we get the performance benefits of a hardcoded string literal, while keeping everything DRY (and therefore hard to inadvertently break).  
 
22 Comments

Posted in .Net, WPF

 

Leave a Reply

 

 
  1. The Morning Brew - Chris Alcock » The Morning Brew #943

    22 September 2011 at 8:34 am

    [...] Raising the right PropertyChanged with C# ’s Caller Info Attributes – Rob Fonseca-Ensor discusses a part of C#5 which did not make it into the //Build/ released Developer Previews, a useful feature allowing the calling member name to be automatically passed as a parameter, which will make implementing things like RaisePropertyChanged much easier. [...]

     
  2. Dew Drop – September 26, 2011 | Alvin Ashcraft's Morning Dew

    26 September 2011 at 1:14 pm

    [...] Raising the right PropertyChanged with C# 5?s Caller Info Attributes (Rob Fonseca-Ensor) [...]

     
  3. Stefan Z Camilleri

    26 September 2011 at 2:26 pm

    This is actually great Rob… magic strings are one of the worst smelling pieces of code imho… I can also see other areas where this would be particularly handy, for example in logging and instrumentation.

     
  4. Sam Sha

    27 September 2011 at 8:06 am

    why “var copy = PropertyChanged;” ?

     
    • Rob

      27 September 2011 at 8:10 am

      Hi Sam, It’s a quick way of making your event threadsafe. Without the local copy of the event (“copy”), if the last handler unsubscribes just after you check for null, it will then become null, but you’ll still try to invoke it. NullRefenceException FTL. Maybe this event doesn’t need to be threadsafe, it’s just something I always, always do.

      P.S. I updated the code to invoke copy instead of PropertyChanged – don’t know what i was thinking…

       
      • Sam Sha

        27 September 2011 at 8:18 am

        I get it, thank u

         
  5. Andy Lowry

    5 October 2011 at 6:41 pm

    This is great, none of the current “solutions” have really solved the problem for me.

    My concern is that we still have to handle the strings in the client.

     
    • Rob

      5 October 2011 at 7:35 pm

      Hi Andy: what do you mean by “handle strings in the client”

       
      • Andy Lowry

        5 October 2011 at 7:53 pm

        Hi Rob, unless your binding using WPF or some other library that handles the dirty work for you. The client of your INotifyPropertyChanged class needs to handle the PropertyChanged event and then use the string name to determine which property has changed. This still has the same problems as before.

        I think INotifyPropertyChanged is the problem. It would be nice to replace it with something easier to use.

         
        • Rob

          6 October 2011 at 12:35 am

          Oh sure I see. We have a rule on our project: INPC is only for WPF’s benefit. If your code needs to depend on a property changing, then we implement a plain event specifically for that property…

           
  6. Scott Holodak

    5 October 2011 at 6:58 pm

    Is there any shortcut for RaisePropertyChanged on auto-properties? i.e., [RaisePropertyChanged] public string UserName { get; set; }

     
    • Rob

      5 October 2011 at 7:32 pm

      Sure, but you have to use an AOP framework like PostSharp – just search for “INotifyPropertyChanged AOP”

       
    • EvAlex

      25 October 2012 at 7:29 am

       
  7. Caleb Vear

    6 October 2011 at 12:33 am

    You can just use NotifyPropertyWeaver now and you don’t even need to implement the properties, just use auto properties.

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

     
  8. Christoph

    6 October 2011 at 8:57 am

    That is why I always thought a “nameof()” operator would be an awesome addition to the language (as proposed here http://codefluff.blogspot.com/2010/05/case-for-nameof-operator.html ) to get rid of all the magic strings. At least now there will be a few less of them in c#5.

     
    • Rob

      6 October 2011 at 10:42 am

      “nameof” is exactly what i was hoping would be added to C# in order to solve this (although it would be a more general solution if you got a System.Reflection.MemberInfo back – to closer match typeof()).

       
  9. Tom

    18 October 2011 at 8:41 pm

    You can find a high performance solution to raise property changes without magic strings here: http://tomsundev.wordpress.com/category/articles/update-property-change-notification-without-strings/

     
    • Rob

      28 January 2012 at 4:51 pm

      Not as fast as this one :)

       
  10. shev

    8 March 2012 at 1:22 am

    Nice rehash of an msdn article.