INotifyPropertyChanged, The Anders Hejlsberg Way
This article is part of a series:
- INotifyPropertyChanged, The Anders Hejlsberg Way
- INotifyPropertyChanged, The .NET 4.5 Way
- INotifyPropertyChanged, The .NET 4.5 Way - Revisited
- INotifyPropertyChanged, The .NET 4.6 Way
Back in September I was watching the Build session that Anders Hejlsberg was giving on the Future directions for C# and Visual Basic and something small but interesting stood out to me in the demo code he used.
We're all pretty used to the standard boilerplate implementation of INotifyPropertyChanged that goes like this:
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
private string companyNameValue = String.Empty;
public string CompanyName
{
get { return this.companyNameValue; }
set
{
if (value != this.companyNameValue)
{
this.companyNameValue = value;
NotifyPropertyChanged("CompanyName");
}
}
}
The above code is taken directly from the MSDN article on "How to: Implement the INotifyPropertyChanged Interface". What jumped out at me in Anders code, was that he was doing the check for equality in the helper method and not the property itself. The thought of doing this had crossed my mind before, but how could you create a method that could check for equality for any given type?
Enter the EqualityComparer<T>.Default property.
Using the Equals() method on EqualityComparer<T>.Default we can now create a generic method that compares the equality of two instances of any give type. This gives rise to the following INotifyPropertyChanged implementation that Anders used in his session:
public event PropertyChangedEventHandler PropertyChanged;
private void SetProperty<T>(ref T field, T value, 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, "UnitsInStock");
}
}
This not only reduces the property set implementation down to 1 line in most cases, but sets up a Pit of Success for properly implementing INotifyPropertyChanged in a class/subclass's properties.
Nice.
(Bonus points for anyone who realized the current MSDN example code isn't thread safe and contains a Race Condition.)