Delegates in C#

A delegate type represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. Delegates are similar to the concept of function pointers found in some other languages, but unlike function pointers, delegates are objectoriented and type-safe.
The following example declares and uses a delegate type named Function.

Code Snippet
  1. using System;
  2. delegate double Function(double x);
  3. class Multiplier
  4. {
  5.     double factor;
  6.     public Multiplier(double factor)
  7.     {
  8.         this.factor = factor;
  9.     }
  10.     public double Multiply(double x)
  11.     {
  12.         return x * factor;
  13.     }
  14. }
  15. class Test
  16. {
  17.     static double Square(double x)
  18.     {
  19.         return x * x;
  20.     }
  21.     static double[] Apply(double[] a, Function f)
  22.     {
  23.         double[] result = new double[a.Length];
  24.         for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
  25.         return result;
  26.     }
  27.     static void Main()
  28.     {
  29.         double[] a = { 0.0, 0.5, 1.0 };
  30.         double[] squares = Apply(a, Square);
  31.         double[] sines = Apply(a, Math.Sin);
  32.         Multiplier m = new Multiplier(2.0);
  33.         double[] doubles = Apply(a, m.Multiply);
  34.     }
  35. }

An instance of the Function delegate type can reference any method that takes a double argument and returns a double value. The Apply method applies a given Function to the elements of a double[], returning a double[] with the results. In the Main method, Apply is used to apply three different functions to a double[].

A delegate can reference either a static method (such as Square or Math.Sin in the previous example) or an instance method (such as m.Multiply in the previous example). A delegate that references an instance method also references a particular object, and when the instance method is invoked through the delegate, that object becomes this in the invocation.

Delegates can also be created using anonymous functions, which are “in-line methods” that are created on the fly. Anonymous functions can see the local variables of the surrounding methods. Thus the multiplier example above can be written more easily without using a Multiplier class:

double[] doubles =  Apply(a, (double x) => x * 2.0);

An interesting and useful property of a delegate is that it does not know or care about the class of the method it references; all that matters is that the referenced method has the same parameters and return type as the delegate.

Post a Comment