Delegates in C# 3.0

Delegates in C# has been around since 1.0. But every occasion when i want to use delegates i end up goggling for an example. so i decided to write a posting  that i can consult every time for its basic usage.

Delegate allows a caller and target to compromise on a definition of a method which includes the parameter type and its return type. Delegates provide a level of indirection because it allows you to dynamically wire a method to the target using callback mechanism.

image

 

Lets drill through the above example to identity key behaviors to remember. I am first declaring a delegate that returns a boolean and accepts an integer. We then specify two different implementations of that delegate. Both those implementations needs to meet the method definition specified by the delegate. Notice that IsEven is declared as static method and IsGreaterThan5 is declared as instance level method and both of them complies to the definition of the delegate.

In static void main we create an instance of Program class and call Run method on it. As we proceed further in exploring the code i will explain why i went through the trouble of creating an instance of the class and calling run method on it. For now let's move on further with our exploration of the code.

In the run method, we create a reference to the delegate Check and assign it to a method. Notice we are using short hand version of assigning a method to a delegate. We could equally written this line of code as follows

Check iseven = new Check(IsEven);

This was the syntax that was around 1.1. With C# 2.0 you can now use a simpler syntax to a assign a method.

In the next line we assign a second method to the delegate. This is called the multicast delegate where a delegate method references more than 1 target or method. The plus += operator is used to add those methods to the invocation list.  We then call the delegate as if we are calling a method but in this case it actually calls both implementations of the delegates IsEven and IsGreaterThan5. One drawback to the way we are calling the delegate is, if your delegate's method definition has return type other than void and you are using multicast delegates than you will only receive the value returned from the last method added to the invocation list. Value returned from the methods added to invocation list prior to the last one would be lost.

In the last section of the code we are actually calling the target to check to see if it evaluates to the instance we are in and result is true. This illustrates a very important concept that when a delegate points to a method that is an instance level as compared to static, then it is the responsibility of the delegate to maintain both the reference to the method as well as a reference to the instance of that method.

Another concept that i consider discussing in terms of delegate is covariance. Its a feature in the delegate which allows polymorphic behavior. Basically if your delegate return type is an Person, you do not necessarily have to return Person type from the implementations of that delegate. Your implementation could actually return concrete type of Person such as an Employee

image

 

From the example above you will observe that our delegate returns a Person but our implementation of the method actually returns an employee. When we invoke the delegate, since the return type of the delegate is Person we need to cast it to employee to get the more specific class.

No Comments