Introduction
Delegates are a concept that for some reason are always confusing. I still have to Google delegates every time I want to use them to get the syntax correct. Let's see if we can dumb down delegates to something a bit more understandable. This is a primer article that is very, very basic, it doesn't even get into talking about events. There are a lot of articles out there that explain Delegates and Events, but I think that a lot of people are lost reading these articles because you need to understand the basics first. This is my crack at the basics, I hope this helps as this is a difficult topic to explain.
Definition: Delegate "a person designated to act for or represent another or others"
private delegate int MathFunction( int n1, int n2 );
private MathFunction adderFunction;
A delegate is a variable that holds a function. It's that simple, I can define a variable of type MathFunction
and assign it one of my functions, then later instead of calling a specific function I can use the variable like a function and it will call the function that it was assigned earlier.
There are many types that can be used when declaring a variable. int
, string
and boolean
are some of the native types that can be used. Developers can define their own types by defining Classes
, Delegates
, Enums
and Structs
in their code. Above we defined a new Delegate Type
called MathFunction
. We can now use this type when declaring variables. In the code example above, we create a variable called adderFunction
which is of type MathFunction
. The Type MathFunction
is a delegate, which means that it can be used like a function and when executed it will call a specific function on that function's behalf. Getting back to the original definition of a delegate: "a variable designed to act for a function".
Using the Code
private delegate int MathFunction( int n1, int n2 );
private MathFunction adderFunction;
static void Main()
{
adderFunction = Add;
int res = adderFunction( 1, 2 );
}
private int Add( int n1, int n2 )
{
return n1 + n2;
}
We've created a new Type in the system called MathFunction
, we used this type to declare a variable called adderFunction
. This variable is assigned the function Add
. The variable adderFunction
can be called like a function adderFunction(5, 10);
and it will call the real function Add
.
A function can differ in its return type, its number of arguments and the types of those arguments. We defined the delegate type MathFunction
to specifically state that a variable declared of this type can be used like a function that takes two int
arguments and returns a type int
. Now that we have defined the signature (or prototype) of the function that this variable can hold, we can now assign the variable a real function that matches exactly that signature.
Real World Example
Have you ever written a function that does a bunch of stuff, then something specific, then a bunch of stuff again. Now Copy and Paste that function 5 times and change only those 3 or 4 lines of specific code in the middle... Wouldn't it be nice if you could, as an argument, pass in a few lines of code then have only one function that did all the overhead stuff but ran those of 4 lines of specific code in the middle??? This is a textbook example for delegates.
For example, when you are talking with a Web server you have a lot of overhead before and after the actual Web call, like logging, timings, handling errors, etc. The MakeWebCall()
function implements all of this overhead, but you need to run 3 or 4 lines of specific code to parse the response. Yes, there's other ways of doing this w/o delegates... Rather than copy and paste this function for each type of server call you need to issue, handle this problem by adding an argument to the MakeWebCall
function that is a delegate. This delegate takes in the HttpWebResponse
object, performs its specific parsing logic and then returns a string
(or maybe raises an error). See the code below:
private delegate string dgProcessResponse( HttpWebResponse response );
private string MakeWebCall( string url, dgProcessResponse ProcessResponseFunction )
{
string sResponse = String.Empty;
try
{
HttpWebRequest req = WebRequest.Create( url ) as HttpWebRequest;
HttpWebResponse response = req.GetResponse() as HttpWebResponse;
if( ProcessResponseFunction != null )
{
sResponse = ProcessResponseFunction( response );
}
}
catch( Exception ex )
{
}
finally
{
}
return sResponse;
}
Points of Interest
Andrew D. Weiss
Software Engineer