Delegates and Events

Event-driven programming is great. It simplifies conceptual models, not to mention makes it easy to wait for something to occur — instead of looping in a busy-wait cycle and polling every few milliseconds for it.

Pretty much every C# developer will have seen code like this:


private void button1_Click(object sender, EventArgs e)
{
}

This is the code generated when you add a button to your form and double-click on it. The IDE does some clever hiding to put part of this code in your Form1.Designer.cs file, and the results here.

Say you wanted to add your own event, just like a button-click. Not to a GUI class, but to any class. How do you do it?

If you have a C++ background, you remember pointers–a conceptual memory address that points to something. Pointers can point to functions, too; if you think of them this way, then a pointer is essentially a placeholder for a function that has a specific signature.

Events work the same way; they have essentially two parts:

  1. The placeholder (or type) of function, and
  2. The actual “event” that you can see and add events to

The “type” of a function is called a Delegate. In C# parlance, a delegate is a way of saying “I’ll take any function that has this signature.”

Let’s say we’re building a virtual phone application, and we want an event to indicate when the call connected, so we can update the GUI to show it to the user. How do we do this?

First, the Delegate

Let’s think. Anyone who listens to this event probably doesn’t need to know much; they know that the call connected. Maybe, for the sake of learning, we’ll provide them with the name of the person they connected to (which we look up from our address book).

Let’s create the delegate; that is, the method signature that all listening events need to conform to. It would look something like this:


public delegate void ConnectOccurredHandler(string connectedTo);

This delegate is a template for a function that … what? That has no return value, and receives one string, “connectedTo,” which will have the name of the person we’re talking to.

This means any event-handler functions that “listen” for this event will have this same signature. What’s next?

Second, the Event

Going back to the form with button-click example, let’s dig a little deeper; go into your form function (maybe Form_Load) and type: “button1.Click”, you should see an item with a lightning-bolt symbol, signifying that this is an event you can listen to.

How do we add that event to our class, the one with the delegate? Simply write:

public event ConnectOccurredHandler ConnectOccurred;

Sure enough, if you try to access Phone.Instance.ConnectOccurred, you’ll see the event! Wow! But there’s one missing piece–the code that actually dispatches the event, and tells all the listeners that it occurred. How do we add that? Simple; wherever you want to raise the event, just add:


if (this.ConnectOccurred != null) {
personWeCalled = AddressBook.FindPersonByNumber(phoneNumber);
this.ConnectOccurred.Invoke(personWeCalled);
}

(The null check just makes sure that if nobody is listening, the application doesn’t crash.) This code triggers the event, and passes out the name of the person we’ve connected to, so that all the event listeners have that information available.

Incidentally, There’s a synchronous version of Invoke called BeginInvoke; I haven’t used it, so I won’t go there. Now, your event triggers at the correct time, and passes out the information it should. How do we listen for this event?

Finally, the World!

Ok, maybe not the world, but let’s add some event listeners. Go ahead and add a form, with code like so:


phoneInstance.ConnectOccurred += new ConnectOccurredHandler(this.phoneInstance_ConnectOccurred);

You’ll notice when you type “+=”, if you press tab twice, Visual Studio will add the handler function name and create a stubbed-out method, like so:


private void phoneInstance_ConnectOccurred(string connectedTo) {
throw new NotImplementedException();
}

You can go ahead and write whatever event-handling code you want, using the connectedTo string to update the GUI accordingly.

Viola! Event handlers and delegates, made easy.

About Ashiq Alibhai, PMP

Ashiq has been coding C# since 2005. A desktop, web, and RIA application developer, he's touched ASP.NET MVC, ActiveRecord, Silverlight, NUnit, and all kinds of exciting .NET technologies. He started C# City in order to accelerate his .NET learning.
This entry was posted in Core .NET, Silverlight, Web, Wndows Forms and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *