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:
{
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:
{
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:
{
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:
{
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. And if any of you have used this syntax in interesting ways, feel free to tell us about it in the comments (and, of course, questions are always welcome).
10/19/2007 - 15:33
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:
{
add { this.textBox1.TextChanged += value; }
remove { this.textBox1.TextChanged -= value; }
}
11/10/2007 - 12:50
get, set, add, remove and value are not keywords in C#, though they apparently act like keywords in a property definition block.
05/30/2008 - 04:21
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).
{
this.handlersThread.Add(value, Thread.CurrentThread);
//We know that Current thread must be UI thread
//of that specific control other while expection
//will be thrown at registering time.
}
remove
{
this.handlersThread.Remove(value);
}
06/10/2009 - 04:16
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.
Add Comment
[language] [/language]
Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]
See here for supported languages.
Javascript must be enabled to submit anonymous comments - or you can login.