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.
Comments
Post a Comment