Events in C# can be weird little beasts. We have talked about how to use and create them before, but really that article only scratches the surface. At first events seem like a special construct, all by themselves in the C# world. But then, after a while (And after you learn about delegates), you realize that all they really are are multicast delegates. But then, even longer after that, you realize that while it may be just a multicast delegate underneath, there are a couple things on top that make the C# event unique.
Or at least, that is the progression of knowledge that happened for me.
And today we are going to talk about what triggered my transition to
that third state of thinking about events - event accessors. It turns
out that as a .NET programmer you have much more control over events
then you might think at first, because you can actually override the add
and removal operators for an event. Those += and -= operators? You
can control what actually happens when they are used.
So you are probably wondering what the syntax is to do this. It is actually very similar to a syntax structure that you are probably already quite familiar with - the property get/set syntax. The main difference is that in this case we are not getting/setting, we are adding/removing:
public event EventHandler MyEvent
{
add
{
}
remove
{
}
}
So in this case, using the += operator on MyEvent would enter the
add block, and the -= operator would enter the remove block. Now,
obviously in this case, nothing would happen, because we don't do
anything in either case.
So lets take a look at some code that duplicates the normal event behavior:
class MyClass
{
private event EventHandler MyPrivateEvent;
public event EventHandler MyEvent
{
add
{
MyPrivateEvent += value;
}
remove
{
MyPrivateEvent -= value;
}
}
}
Again, very similar to the get/set property definition, where value
ends up holding what was passed into the property. And in this case,
value will always be of type EventHandler. Essentially, this extends
to events the standard object oriented abstraction of always having
public getters and setters for a private member field.
That code isn't really very interesting, because it implements the exact behavior of the standard C# event. But there are a couple ways it can come in handy. One common one, I have found, is for debugging purposes - you can easily throw some debugging info in the add and remove accessors:
class MyClass
{
private event EventHandler MyPrivateEvent;
public event EventHandler MyEvent
{
add
{
Debug.WriteLine("Attaching To MyEvent");
MyPrivateEvent += value;
}
remove
{
MyPrivateEvent -= value;
Debug.WriteLine("Detaching From MyEvent");
}
}
}
And of course you can do whatever else you want to do in add and remove accessors - maybe initialize some other code, maybe not even attach the event at all in certain cases.
One of the odder possibilities with these accessors is to not actually use an event as the underlying delegate holding structure. That might sound kind of weird, but it should make sense when you look at the code:
class MyClass
{
private List<EventHandler> MyEventStorage = new List<EventHandler>();
public event EventHandler MyEvent
{
add
{
MyEventStorage.Add(value);
}
remove
{
MyEventStorage.Remove(value);
}
}
//And with this technique, you can have
//stuff like this
public void ClearAttached()
{
MyEventStorage.Clear();
}
}
I have never had reason to use this manner of event delegate storage,
but I have a feeling it could come in handy if you wanted to be able to
actually work with the list of event hooks. Take, for instance, the
ClearAttached method - the equivalent code using a normal event object
would actually be somewhat complicated. Granted, the code to fire the
list of events would be a little more complex then the normal event
firing code, but hey, there are always trade offs.
And that is all I have on event accessors - you can check out Microsoft's docs for other examples of why this syntax is useful.
I have wondered why these two reserved words (add, remove) are not documented in the standard MSDN Library documentation for Visual Studio.
Anyway, there is a case where I always use it. That is when creating a UserControl that has child controls which events must be public. The solution is to use that kind of mapping:
get, set, add, remove and value are not keywords in C#, though they apparently act like keywords in a property definition block.
Great Tutorial I think, it is very usefull to solve a problem we can face in WPF data binding as we cannot update ObservableCollection from other thread (cross thread).
For me, I had a static event! (thats bad i know but should be legal), anyway i ran into a problem where my app get blocked when un-register to the event in my library, nothing fixed this but implementing this way in my library!!! anyway i have to investigate more about this.