Well if you have learned to code in C or C++ language then you must be aware of pointers to functions in these languages, similar kind of work is done by Delegates in C#.

Delegates in C#

A delegate is like a pointer to a function. It is a reference type data type and it holds the reference of a method. The reference can be changed at runtime.All the delegates are implicitly derived from System.Delegate class.You can take advantage of delegates in C# to implement events and call back methods. A multicast delegate is one that can point to one or more methods that have identical signatures.

Delegate can be declared using delegate keyword.

Syntax to declare delegate

delegate double DoubleOp(double x);

In the above declaration, DoubleOp is a function which takes double as a argument and also returns double, which is used to perform mathematical operations, it can be used to call Math Operations using Delegates.

So, basically looking at the above example syntax for the delegate would be

delegate <return type> <delegate-name> <parameter list>

Here is the complete Delegate example:

using System;

public class MathOPs
{
    public static double Multiply(double value)
    {
        return value * 2;
    }

    public static double Square(double value)
    {

        return value * value;

    }

}


delegate double DoubleOp(double x);
 

class Application
{
    static void Main()
    {
        DoubleOp[] operations =
            {
               MathOPs.Multiply,
               MathOPs.Square
            };

        for (int i = 0; i < operations.Length; i++)
        {
            Console.WriteLine("Operation[{0}]:", i);
            ProcessAndDisplayNumber(operations[i], 5.0);
            ProcessAndDisplayNumber(operations[i], 13.55);
            ProcessAndDisplayNumber(operations[i], 1.732);
            Console.WriteLine();
        }
        Console.ReadLine();
    }
 
    static void ProcessAndDisplayNumber(DoubleOp action, double value)
    {

        double result = action(value);

        Console.WriteLine(

           "Value : {0}  Result : {1}", value, result);

    }

}

Output of the above code will be

Operation[0]:
Value : 5  Result : 10
Value : 13.55  Result : 27.1
Value : 1.732  Result : 3.464

Operation[1]:
Value : 5  Result : 25
Value : 13.55  Result : 183.6025
Value : 1.732  Result : 2.999824

Multicast delegate:

The delegate can points to multiple methods. Multicast delegate is a delegate which holds a reference to more than one method. The "+" operator adds a function to the delegate object and the "-" operator removes an existing function from a delegate object.

Here is an example of multicast delegate

using System;

delegate void delet(int a, int b);

public class Oper {
 public static void Add(int a, int b) {
  Console.WriteLine("{0} + {1} = {2}", a, b, a + b);
 }
 public static void Sub(int a, int b) {
  Console.WriteLine("{0} - {1} = {2}", a, b, a - b);
 }
}

public class program {

 static void Main() {
  delet del = new delet(Oper.Add);
  //multicast delegate here
  del += new delet(Oper.Sub);
  del(4, 2);
  
  del -= new delet(Oper.Sub);
  del(1, 9);
  Console.Read();
 }

}

Output of the above code will be

4 + 2 = 6
4 - 2 = 2
1 + 9 = 10

Advantages of using Delegates in C#:

  • Can lead to easy reuse of code
  • Can provide a great amount of flexibility in your designs
  • Allow you to develop libraries and classes that are easily extensible, since it provides an easy way to hook in other functionality (for example, a where clause in LINQ can use a delegate [Func<T,bool>] to filter on, without having to write new code in the Where method

Where or When to use delegates?

Suppose you want to write a procedure to integrate some real-valued function f (x) over some interval [a, b]. Say we want to use the 3-Point Gaussian method to do this 

// 'f' is the integrand we want to integrate over [a, b] with 'n' subintervals.
static double Gauss3(Integrand f, double a, double b, int n) {
  double res = 0;

  // some code here
  // ...

  return res;
}

So we can pass in any,Integrand f, and get its definite integral over the closed interval.Just what type should Integrand be?

Without Delegates

Well, without delegates, we'd need some sort of interface with a single method, say eval declared as follows:

// Interface describing real-valued functions of one variable.
interface Integrand {
  double eval(double x);
}

Then we'd need to create a whole bunch of classes implementing this interface, as follows:

// Some function
class MyFunc1 : Integrand {
  public double eval(double x) {
    return /* some_result */ ;
  }
}

// Some other function
class MyFunc2 : Integrand {
  public double eval(double x) {
    return /* some_result */ ;
  }
}

Then to use them in our Gauss3 method, we need to invoke it as follows:

double res1 = Gauss3(new MyFunc1(), -1, 1, 16);
double res2 = Gauss3(new MyFunc2(), 0, Math.PI, 16);

And Gauss3 needs to do the look like the following:

static double Gauss3(Integrand f, double a, double b, int n) {
  // Use the integrand passed in:
  f.eval(x);
}

So we need to do all that just to use our arbitrary functions in Guass3.

With Delegates

Declare your delegate first

public delegate double Integrand(double x);

Now we can define some static (or not) functions adhering to that prototype:

class Program {
   public delegate double Integrand(double x);   
   // Define implementations to above delegate 
   // with similar input and output types
   static double MyFunc1(double x) { /* ... */ }
   static double MyFunc2(double x) { /* ... */ }
   // ... etc ...

   public static double Gauss3(Integrand f, ...) { 
      // Now just call the function naturally, no f.eval() stuff.
      double a = f(x); 
      // ...
   }

   // Let's use it
   static void Main() {
     // Just pass the function in naturally (well, its reference).
     double res = Gauss3(MyFunc1, a, b, n);
     double res = Gauss3(MyFunc2, a, b, n);    
   }
}
//example source
// https://stackoverflow.com/a/2020501

Now, looking at the above example you can see, we didn't create any interface, no .eval stuff, no object instantiation, just simple function-pointer like usage, for a simple task.