Friday, 5 August 2011

Delegates and Events in C#





Introduction





Callback functions are an important part of programming in Windows. If you have background in C or C++ programming, you have seen callbacks used in many of the Windows APIs.  Callback functions are really pointers to a method call. In .NET World, pointers has been replaced with the concept of delegates. What makes them special is that unlike the C function pointer, the .NET delegate is type safe.

Declaring Delegates in C#

Delegates exists for situations in which you want to pass methods arounds to other methods. Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked.



delegate void DoThisThing(int x);



From the code above, you have defined a delegate called
do this thing

and you have indicated that each instance of this delegate can hold a reference to a method that takes one int parameter and returns void.

An interesting and useful property of a delegate is that it does not know or care about the class of the object that it references. Any object will do; all that matters is that the method's argument types and return type match the delegate's. This makes delegates perfectly suited for
"anonymous"invocation.

Another example of delegates that take two parameters and return double.

delegate double DoThisDoubleThing(double first,double second) ;

The syntax is similar like method declaration,except that there is no method body and the definition is prefixed with the keyword delegate.

Using Delegates in C#

The following code snippet demonstrates the basic and simple use of a delegate.

private delegate string PrintString();static void Main (string [] args)

{

int x = 40;

PrintString oDel =
new PrintString(x.ToString);

Console.WriteLine(
"String from Delegates is " + oDel());

}

In the code above, you instantiate a delegate called
PrintString that accept no parameters and return string. The reference method of the delegates (x.ToString()) must match the signature of the delegates that you defined. So in this case, you will get a compilation error if you tried to refer the delegates with the methods that require parameters.

One feature of delegates is that they are type-safe to the extend that they ensure the signature of the method being called. However, interestingly they do not care what type of object the method is being called against or even whether the method is static method or instance method.

Another simple example invoke a method asynchronously using delegates.

class Program

{

public delegate void PrintingDelegate(string sData);static void Main(string[] args)

{

PrintingDelegate oDel =
new PrintingDelegate(PrintOne);

oDel(
"MyName");

}

public static void PrintOne(string sData)

{

Console.WriteLine(sData);

Console.ReadLine();

}

}

MultiCast Delegates in C#

Being able to point to member functions is nice, but there are more tricks you can do with delegates. In C#, delegates are multicast, which means that they can point to more than one function at a time (that is, they're based off the
System.MulticastDelegate type). A multicast delegate maintains a list of functions that will all be called when the delegate is invoked. The code snippet below will show you how to write a multicast delegates in c#

class Program

{

delegate void TestMultiCastDelegate();static void Main(string[] args)

{

TestMultiCastDelegate oDel =
new TestMultiCastDelegate(PrintOne);

oDel +=
new TestMultiCastDelegate(PrintTwo);

oDel();

Console.ReadLine();

}

public static void PrintOne()

{

Console.WriteLine(
"One");

}

public static void PrintTwo()

{

Console.WriteLine(
"Two");

}

}



Multicast delegates recognizes the operators + and += or - and -=. You use +=, if you like to add method references to your delegate and use -= if you like to remove the method references from your delegate.

Events Delegates in C#

The Event model in C# finds its roots in the event programming model that is popular in asynchronous programming. Typical .NET events include things like the mouse actions and keyboard key presses that your application captures. Events are better than delegates for implementing callbacks, because they provide more protection. In fact, the underlying implementation of an event is actually a delegate


With delegates, an assignment of a delegate (=), rather than an add (+=) will wipe out all delegates previously added to its invocation list, which is something you generally don't want happening to events that your code raises.


The basic foundation behind this programming model is the idea of "publisher and subscribers." In this model, you have publishers who will do some logic and publish an "event." Publishers will then send out their event only to subscribers who have subscribed to receive the specific event.

Generating Events

Receiving events and responding to them is only one side of story. To be really useful  you need the ability to generate events and raise them in your code. The example in this section below looks at creating,raising,receiving an event.


Steps you need to generate and create new event.


First, we need to create a delegate for the event.

public delegate void MyEventHandler(object sender, EventArgs e);

The delegate defines the parameters sent to the event handlers. Thus any class that wants to handle this event must have a handler method which has the same return type and argument list as this delegate. Here as you can see, the first parameter is an object. In real-world cases event handlers are normally passed a reference to the sending object. The second parameter is a System.EventArgs derived class. In the code above, I use the EventArgs objects that being provided by .NET framework. You can create your own EventArgs classes by inheriting the EventArgs class.


System.EventArgs is the base class for encapsulating event related data. We use it to send information regarding the event to its handler.


Second, Create an Event based on the delegate that we create above.

public static event MyTestHandler MyEvent;

An event is declared like a delegate type variable, except that the keyword
event precedes the event declaration.

Third, Create a function that invokes the event.


protected static void OnMyTestEvent(object sender, EventArgs e)

{

if (MyEvent != null)

{

MyEvent(sender, e);

}

}

OnMyTestEvent 
will be null if no client has hooked up a delegate to the event. We need to check if it is null unless you want to see an exception raised.

Fourth, Hook the Event and Raise the Event

MyEvent +=
new MyTestHandler(MyEventHandler);

OnMyTestEvent(
null, e);

Once you have hooked the Event with the event handler, the MyEvent object will not be null and therefore it will then call the reference method from the delegates.

Complete code snippet


class Program

{

public delegate void MyTestHandler(object o, EventArgs e);public static event MyTestHandler MyEvent;static void Main(string[] args)

{

//Creating the Event ArgumentsEventArgs e = new EventArgs();//Hook the Event MyEvent += new MyTestHandler(MyEventHandler);//Raise the EventOnMyTestEvent(null, e);

}

static void MyEventHandler(object o, EventArgs e)

{

Console.WriteLine(
"Event being called.");

Console.ReadLine();

}

protected static void OnMyTestEvent(object sender, EventArgs e)

{

if (MyEvent != null)

{

MyEvent(sender, e);

}

}

}

Conclusion



Delegates

Delegate is type-safe object which can point to any function to invoke them synchronously and asynchronously

No comments:

Post a Comment