Using Delegates in C#
Introduction
Delegates encapsulate a method. All they do is provide an alternate way to call (‘invoke’) a method. This concept has been around for a while (function pointers in C – and other languages). In C#, there are three things to remember when using delegates. Just use the acronym D-A-I for ‘Declare’, ‘Assign’ and ‘Invoke’.
Declaring a delegate
Say you have a function that takes two strings, concatenates them and returns the result. So the signature would look something like the snippet below.
private static string stringCat(string a, string b)
{
return String.Concat(a,b);
}
To encapsulate this function within a delegate, one declares a delegate as follows:
delegate string del(string a, string b);
Assigning a Delegate
Once you have it declared (remember, it is simply encapsulating a function), you will need to specify which function you want to use it on. This is the assignment step – and is illustrated in the snippet below.
private static string DelegateSimpleInvoke()
{
// assign your delegate to the stringCat target
del x = stringCat;
// invoke the delegate (which means 'call your function' indirectly). This should return "ab"
string c = x.Invoke("a","b");
return c;
}
Invoking a Delegate
Once you have assigned a target method for your delegate, you are ready to invoke the delegate (call the method). This is done via the Invoke keyword as shown above. This is where you would pass in the actual argument values to the function.
So, there you have it. In three simple steps – D.A.I. – you can use delegates in C#.
Asynchronous Invocation
A nice advantage of encapsulating a method is that you can invoke it any way you like – synchronously (using Invoke) or asynchronously (using BeginInvoke).
private static string DelegateAsyncInvoke()
{
// assign your delegate to the stringCat target
del x = stringCat;
// invoke the delegate (which means 'call your function' indirectly). This should return "ab"
IAsyncResult result = x.BeginInvoke("a", "b",null,null);
// Do something else while the method execution has not yet completed
while (!result.IsCompleted)
{
Thread.Sleep(500);
Console.Write(".");
}
// Now, the method has finished executing - since result.IsCompleted is true
string c = x.EndInvoke(result);
return c;
}
Common Misconception – Delegates and Async programming
Most people associate the two. Delegates, by themselves, have nothing to do with an asynchronous model of programming. They simply encapsulate a function (any function). Now, once the function is encapsulated, it becomes possible to call it (invoke it) – synchronously OR asynchronously – as you choose. In the case of C#, the built-in delegate class provides you with supporting methods to invoke (the encapsulated method) asynchronously – which is why the misconception occurs. A delegate by itself, doesn’t care about whether you invoke synchronously or asynchronously. Only the client cares. The delegate’s job is to provide encapsulation for your method – and that’s it.
Using a Lambda Expression with a delegate
Notice that there is no assignment step like del x = stringCat in the snippet below. The assignment is done using a lambda expression. How does it know what x and y are? It ‘infers’ them based on the String.Contact function. It figures out that you will need to pass in two strings – and infers that x and y are strings.
/// <summary>
/// same thing as before - without an explicit assignment. Using a lambda expression for assignment.
/// </summary>
private static string DelegatesUsingLambdaExpr()
{
del z = (x,y) => String.Concat(x, y);
return z.Invoke("a", "b");
}
Summary
Delegates are a simple way to encapsulate methods – so that they can be called later. In addition to providing a way for ‘regular’ (synchronous) method invocation, they also provide an easy option to invoke the method asynchronously. Remember D.A.I (Declare, Assign and Invoke) to simplify usage of delegates within your codebase.
What type is “del”? don’t you mean delegate?
ohh I see it is defined here:
delegate string del(string a, string b);