C# Events and Delegates for UNIX developers

Dmitry February 27th, 2007

In this tutorial I’ll explain events and delegates the easy way! The intended audience is UNIX people with minimal C and Java experience. Sending events is super simple in .NET framework. The C# language has “delegate” and “event” keywords.

Delegates are kind of like a C function pointer, and they’re even more like C++/STL functors. Except for the following distinctions:

  1. They’re safe
  2. They also have a multicasting feature. Unlike a C function pointer, you can subscribe multiple callbacks to the delegate. Whenever you invoke a delegate, in return it will call all subscribed methods. More on this later.

So, the whole GUI system in Java or Windows Form is all based on events. It’s also called the “observer” pattern. So, it’s important to get events/delegates mechanism down. In this very simple example we’ll have a Broadcaster and a TV. The broadcaster “fires” and event and everyone that is subscribed to it will get it.

I like to oversimplify things, so to break it down from each side.

The broadcaster:

  • Defines a delegate. Basically it’s syntax is like defining a function prototype in C. The functions the will be subscribing to us will need to have a matching signatures.
  • In order to use a delegate as an “event”, we need to attach it to a class with an event keyword.
  • The broadcaster will have a “fire” method. First we make a defensive copy of the event, to avoid a possible race condition. Second, we check if its null (no one is subscribed to us yet). Then we call it. By calling a delegate (once), it calls all of the subscribed methods in the order they were attached. They way it works is delegate keeps track of all the functions that are subscribed to it. You can access them by del.GetInvokationList().

The TV:

  • Just has one method, nothing special, no special keywords. But … this method’s signature is the same as the delegate’s.

The Program Driver:

  • We create the Broadcaster and TV objects
  • We fire an event from broadcaster, no one is listening at this point
  • We attach a bunch of listeners to broadcaster
  • We fire again and watch what happens

Things to note:

  • We can attach any method to a delegate with += operator. The only requirement is the method has to have the same signature.
  • In broadcaster.fire() by calling on a delegate, we’re invoking the chain of subscribed methods. Some of them are anonymous. Watch for the output and how .NET names them. Its interesting.

Here is the code:

C#:
  1. class Broadcaster {// event fieldpublic event NewProgramDel NewProgramEvent;public void Fire() {msg("Trying to fire an event");NewProgramDel tmp = NewProgramEvent;if (tmp != null) {msg("About to call a delegate with following subscribers:");foreach (Delegate d in tmp.GetInvocationList()) {Console.WriteLine("* {0}", d.Method );}// calls the delegatetmp(this, new EventArgs());// delegates are kind of like function pointers, except:// the above line calls ALL of the "subscribers" to our delegate// (in our example there are two subscribers)} else {msg("No one is listening me!");}}private static void msg(string s) {Console.WriteLine("Broadcaster: {0}", s);}}

C#:
  1. class Tv {// This Callback method has the same signature as the delegate.// thats why we can subscribe this method to a delegatepublic void Callback(object sender, EventArgs args) {Console.WriteLine("TV: Got a msg from {0}", sender.ToString());}}

C#:
  1. class Program {static void Main(string[] args) {Broadcaster b = new Broadcaster();Tv tv = new Tv();// no one is listening yetb.Fire();/* subscribe some methods with += operator */// subscribe a method from some other objectb.NewProgramEvent += tv.Callback;// subscribe a method from our classb.NewProgramEvent += new NewProgramDel(b_NewProgramEvent);// this is kinda cool, its a new feature in C# 2.0. This creates// an anonymous function and subscribes it.b.NewProgramEvent += delegate(object sender, EventArgs e) {Console.WriteLine("hi, I am anonymous method!");};// watch the output ... see how this anonymous method gets// named to b__1(). Cool.b.NewProgramEvent += delegate(object sender, EventArgs e) {Console.WriteLine("I am yet another anonymous method!");};b.Fire();// so the console doesn't die. Ahh. I miss my xterm.Console.ReadLine();}// This method has the same signature as the delegate.// thats why we can subscribe this method to a delegatestatic void b_NewProgramEvent(object sender, EventArgs args) {Console.WriteLine("hi, I am another subscriber");}}

Download The Code:

Trackback URI | Comments RSS

Leave a Reply