This article is about a curiosity in C# that I stumbled upon. What's curious about it is that help documentation is almost non-existent, and I haven't read anything about it in any of the hundreds of pages on .NET that I've read. (However, they are mentioned in the .NET Framework SDK Tool Developers Guide (by default) folder in the CLI specification documents written by Jim Miller.) The curiosity I am talking about are add and remove accessor methods for events. In fact, they are so sketchily documented that I even have to venture a guess at their names, so I'll call them event subscription methods.
In this article, I will introduce the add and remove event subscription accessor methods, and you can be the envy of all your friends. I first caught wind of these methods in the Anakrino.exe disassembler downloaded from the Web. Perhaps you will find them useful in your daily C# juggernaut.
By now, most of us have heard that events in .NET are managed by something called a delegate. Boiled down to its essence, a delegate is the object-oriented equivalent of a function pointer. Multicast delegates are a list of function pointers. When the event associated with a multicast delegate is raised, all the methods in the invocation list are called. This is referred to as multicasting. It is a clever adjustment to plain old function pointers.
In C#, we declare new delegates by writing a method signature with the keyword delegate in the signature statement. For example, the following
public delegate void MyDelegate(int x, int y);
declares a delegate with a two-integer signature. To associate function pointers with this delegate, we could declare an event whose type is MyDelegate, such as
public event MyDelegate OnTwoIntegers;
With the delegate and the event defined, we could now add as many function pointers into OnTwoIntegers' invocation list as desired by using the overloaded += operator. If you look in the InitializeComponent method for any Windows Forms application, you are likely to see examples of these kinds of statements. Here are two such statements from my sample code:
this.Load += new System.EventHandler(this.Form1_Load); this.Closed += new System.EventHandler(this.Form1_Closed);
Both statements are dependent on a delegate named EventHandler and an overloaded += operator that knows that an event on the left and a delegate on the right means to insert the delegate cum function pointer into a list of function pointers defined by the base class System.Delegate. Yes, that's right. Our first statement using the keyword delegate is sort of an abbreviated class inheritance statement.
Function pointers, events, and delegates are all very powerful and useful things for dynamic programming, and so far we have used all of these aspects of .NET programming with no surprises. Now, to paraphrase Lewis Carroll's Alice things get "curiouser and curiouser".