C# Tutorial - Event Accessors [Beginner]


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