INotifyPropertyChanged (1 of 3) – without the strings

3
April 5, 2013 // wpf

If you’ve worked with WPF, you’ve probably encountered INotifyPropertyChanged.  It is a great notification mechanism, but it has a few common code smells we’ll iron out over this three part series.

String based

The default way of raising a notification is to specify the property name with a string.

        private int _iterations;

        public int Iterations
        {
            get { return _iterations; }
            set
            {
                if (_iterations != value)
                {
                    _iterations = value;
                    OnPropertyChanged("Iterations");
                }
            }
        }

        protected void OnPropertyChanged(string propertyName)
        {

It works, but it smells of both fragility (a typo or property rename will silently break it) and redundancy.

Lambda based

A different way of raising a notification is to specify the property name with a lambda expression.

        private int _iterations;

        public int Iterations
        {
            get { return _iterations; }
            set
            {
                if (_iterations != value)
                {
                    _iterations = value;
                    OnPropertyChanged(() => Iterations);
                }
            }
        }

        protected void OnPropertyChanged<T>(Expression<Func<T>> exp)
        {

It works, and no longer smells of fragility.  It is still redundant though, and makes you wonder about performance which we’ll cover shortly.

CallerMemberName based

Now with C# 5 there is another way of raising a notification which is to utilize the CallerMemberName attribute. This new attribute defined in our OnPropertyChanged method will pull the property name for us automatically.

        private int _iterations;

        public int Iterations
        {
            get { return _iterations; }
            set
            {
                if (_iterations != value)
                {
                    _iterations = value;
                    OnPropertyChanged();
                }
            }
        }

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {

It works, no fragility and no redundancy. 🙂

Performance

Back to performance, how do these alternatives stack up?  I created a sample application (attached) that raises a million notifications using each of these three mechanisms. Here’s the results:

Performance image

Performance comparison between string based, lambda based and CallerMemberName based mechanisms.

Our string baseline took 4.857s to raise a million notifications. Using lambda expressions took 8.154s, an increase of nearly 70%. Using CallerMemberName however was nearly identical to the baseline at 4.768s, which is great news since it means we can take advantage of more robust code without any performance concerns!

Hope it helps – stay tuned for the next two parts in the series, where we’ll get rid of backing fields and reversed notifications. 🙂

Code: SteveCadwallader.NotifyPropertyChanged.1of3.zip

Part 2: INotifyPropertyChanged (2 of 3) – without the backing fields
Part 3: INotifyPropertyChanged (3 of 3) – without the reversed notifications

About the author

Steve Cadwallader is a software developer who geeks out on user interfaces, clean code and making things easier.

3 Comments

  1. Nice to know. Very cool new feature of the new C# 🙂

  2. Pingback: ReSharper's Structural Search and Replace - Code Cadwallader

  3. So simple and So straight – Perfect! (thanks)

Leave a Comment