In my last post, I talked about using a Visual Studio code snippet for properties in classes implementing INotifyPropertyChanged:

The code snippet lets me create the properties faster, but it's still a lot of repetitive "setter" code for each.

What if I moved the "has the value changed?" and backing field update logic out of the property setters and replace my NotifyPropertyChanged method with this CheckForPropertyChange method?:

        protected bool CheckForPropertyChange<T>
            (ref T currentValue, T value, params string[] propertyName)
        {
            if (value.Equals(currentValue)) return false;
 
            currentValue = value;
 
            if (PropertyChanged == null) return false;
 
            foreach (string name in propertyName)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
 
            return true;
        }

 

…so my property code can look like this:

        private string _statusMessage;
        public string StatusMessage
        {
            get { return _statusMessage; }
            set { CheckForPropertyChange<string>(ref _statusMessage, value, "StatusMessage"); }
        }

 

Actually, the generic type (<string> in the example above) doesn't have to be explicitly specified in C#, so we can get rid of it:

        private string _statusMessage;
        public string StatusMessage
        {
            get { return _statusMessage; }
            set { CheckForPropertyChange(ref _statusMessage, value, "StatusMessage"); }
        }

 

…and why pass the property name when we can get it via reflection? We can make it as simple as this:

        private string _statusMessage;
        public string StatusMessage
        {
            get { return _statusMessage; }
            set { CheckForPropertyChange(ref _statusMessage, value); }
        }

 

…with an override to our CheckForPropertyChange method:

        protected bool CheckForPropertyChange<T>(ref T currentValue, T value)
        {
            string propertyName = new StackTrace().GetFrame(1).GetMethod().Name
                .Substring(4); // bypass "set_" prefix
 
            return CheckForPropertyChange(ref currentValue, value, propertyName);
        }

 

(Yes, reflection is slow, but in the context of a ViewModel bound to a Silverlight or WPF "business form" view, I doubt very much that there will be a noticeable difference to the user. Don't use it where performance is really, really important, and when optimizing for performance always measure to confirm your assumptions.)

EDIT: 8/2/2010:
See also: INotifyPropertyChanged with less code using Expressions