I often coach or teach .NET developers, and I'm often surprised how some folks write the most complex programs and discuss amazing architectures, but can't get the basics right. So I'm planning to write a series of posts on .NET basics. I'll use C# as a language, but most topics will be equally applicable to Managed C++ or Visual Basic.NET.
In this first post, I want to talk about simple properties with a changed event, as you will often find them on classes used in Windows Forms data binding scenarios. Take as an example a "Name" property of type string. We'll use a backing field called "name". In VB you can't rely on casing to differentiate between the field and the property, so you'd probably call the field "nameValue" or something. The getter will simply return the field, but the setter needs to raise the event in addition to setting the field.
According to .NET standards, the event will be of type EventHandler and be called NameChanged. Any other type or name, and Winforms data binding will not work.
Many people write something along the lines of
private string name;
public string Name
{
get { return name; }
set
{
name = value;
if (NameChanged != null)
{
NameChanged(this, e);
}
}
}
public event EventHandler NameChanged;
But that has approach has two problems associated with it. The first one is the easiest to understand: the NameChanged event will be raised, even if the Name didn't really change. Let's say the value of Name is null and I write
Name = null;
That will raise the event, even though nothing changed. That could result in wasted processing or worse. In the case where two such properties are bound to each other via their events, any assignment to either of them would cause an infinite recursion and a stack overflow. So you need to test if the value really changed before raising the NameChanged event.
The second problem has to do with inheritance. If your class might be used as a base class for derived classes, you need to give those derived classes an easy and efficient mechanism to react to a property change. Raising an event and then subscribing to that event yourself doesn't count as efficient. So what we do instead is create a protected virtual method that raises the event. This allows derived classes to override the method to be notified of property changes. Simple, clean and efficient. According to .NET standards, we'll call the method OnNameChanged. Event raising methods like this one have a single parameter of type EventArgs (or, in the general case, a class derived from EventArgs). That yields the following implementation:
private string name;
public string Name
{
get { return name; }
set
{
if (value != name)
{
name = value;
OnNameChanged(EventArgs.Empty);
}
}
}
public event EventHandler NameChanged;
protected virtual void OnNameChanged(EventArgs e)
{
if (NameChanged != null)
{
NameChanged(this, e);
}
}
You can of course extend this basic pattern. For example you could make the property virtual as well, although that would slow it down considerably. Anyway, the pattern as above is quite a bit of typing as it is, and will cover most cases.
In part 2 of this series, where we talk about an alternative approach: using the INotifyPropertyChanged interface.