Wednesday, 24 October 2012

Delegate Type vs Delegate Instance

In the previous post I talked about the evolution of C# as a language. In this post I'm going to continue the same trend. In this post however the focus in on the elements of C# that are usually misunderstood. Jon has had a lot of experience on Stack Overflow and due to this, he has seen many confusion in the community regarding the concepts covered here. I will summarize the key concepts here. I will also put each section into a new post. I've noticed that the posts are too long for any interested reader !

Delegates

Delegates could be defines as entities encapsulating a behavior with certain parameters and a return type. Now the forms of a delegate's definition has already been covered in my previous post. But there seems to be a confusion about the word delegate since it is both used as the "delegate type" and the "delegate instance". The code below shows the difference between the two:

   
    delegate int DelegateType(int a, int b);

    public int Add(int a, int b)
    {
        return a + b;
    }
...
    DelegateType delegateInstance = Add;
    Console.WriteLine(delegateInstance(3, 4));

As seen in the above code snippet, in order to create a delegate firstly a delegate type should have been declared. With the first line of code we are actually creating a new reference type called DelegateType. This type can then be instantiated, passed to functions and basically used wherever a reference type is used. Also remember that delegates like strings are immutable and thread safe. In the next lines we have created an instance of the delegate type and then invoked it. We could have used the Invoke() method of the delegate instance too but a C# shortcut is to just call it like you call a normal method. Each delegate has an invocation list. When the delegate in invoked all the functions in the invocation list are called. These functions usually have no return type but the last. Since if they do, the return type is just thrown away as the return type of the delegate is the return type of the last element in its invocation list.
In C# 1.0 the delegate instance accepts only functions with exactly the same signature defined by the delegate type. Let's say in the scenario of a parent class human and two sub-classes man and woman and with a function with the signature "void Run(Man)", one would expect to be able to have a function with the signature void Run(Human) added to the invocation list. This however can not be done in C# 1.0. This is also known as parameter contravariance. Another interesting scenario is being able to add a function with a signature that returns a derived type of the return value in the signature defined by the delegate type, also known as covariance. These two scenarios are made possible in C# 2.0 for delegates. The concept is still to be made available for implementing methods of an interface even in C# 4.0.
Another misconception is thinking of "Events" as delegates. Although events in the .Net framework rely heavily on delegates to function, they are not delegates themselves. The way that the framework is implemented however makes them look like delegates. But just like properties that look like fields to the wold outside the scope of the object and actually have getters and setters on the inside, Events are implemented as fields of type of the delegate inside their class and to the outside they seem like fields too but are actually add and delete method pairs that add or delete functions to the invocation list of the delegate field.

No comments:

Post a Comment