Delegates can be tricky to understand. Think of a delegate as a reference to a method (pointer to a function).
What are Delegates?
Technically, a delegate is an object that contains a reference to a method, which can be a member or static method, but not a property. The delegate object can be used like any other object, assigned to a variable and passed as an argument to another method. The delegate can also invoke the method it references, without knowing at compile time which method will be invoked.
A delegate does not know or care about the object or class that contains the method it references. All that matters is the method’s arguments and return type exactly match the delegate’s. This makes delegates well-suited for “anonymous invocation.” The .NET Framework uses delegates extensively for events, callbacks, asynchronous calls and multithreading.
How are Delegates Used?
A delegate is defined by the “delegate” keyword, followed by the return type, delegate name, and method signature. For example:
private delegate Color ColorMethod( Color color );
The “ColorMethod” delegate in the example above is a reference to a method that accepts a Color argument and returns a new Color. Hence, the ColorMethod delegate could reference the following method because they have the same signature:
private Color MakeRed( Color color ) { . . . }
Part of the confusion about delegates results from its syntax. When you want to assign a method to a delegate, you have to create the delegate object with the method as the constructor argument:
ColorMethod method = new ColorMethod( this.MakeBlue );
This syntax makes sense when you understand that a delegate is itself an object, but it also makes for less readable code.
Introducing Delegate Inference
The .NET v2.0 upgrade has simplified delegate assignment with a concept called “delegate inference.” This describes the compiler’s ability to infer from an anonymous method assignment which delegate type to instantiate. Delegate inference allows you to directly assign a method to a delegate variable, without first wrapping it in a delegate object. For example, the assignment above could be written as:
ColorMethod method = this.MakeBlue;
More straightforward, isn’t it?
Delegate Inferences in Action
The following simple example shows how you can use delegates to select which method to execute at run-time:
class ColorManager { public Color ChangeColor( Color color, Color toColor ) { ColorMethod method = null; if (toColor == Color.Red) method = this.MakeRed; else if (toColor == Color.Green) method = this.MakeGreen; else if (toColor == Color.Blue) method = this.MakeBlue; if (method != null) color = method( color ); return color; } private delegate Color ColorMethod( Color color ); private Color MakeRed( Color color ) { return Color.FromArgb( 255, color.G, color.B ); } private Color MakeGreen( Color color ) { return Color.FromArgb( color.R, 255, color.B ); } private Color MakeBlue( Color color ) { return Color.FromArgb( color.R, color.G, 255 ); } }