Delegates in C#

A delegate in C# is similar to a function pointer in C or C++. Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked.

An interesting and useful property of a delegate is that it does not know or care about the class of the object that it references. Any object will do; all that matters is that the method's argument types and return type match the delegate's. This makes delegates perfectly suited for "anonymous" invocation.

The signature of a single cast delegate is shown below:

delegate result-type identifier ([parameters]);

where:

result-type: The result type, which matches the return type of the function.
identifier: The delegate name.
parameters: The Parameters, that the function takes.

A delegate is a type that references a method. Once a delegate is assigned a method, it behaves exactly like that method. The delegate method can be used like any other method, with parameters and a return value.

Delegates have the following properties:

  • Delegates are similar to C++ function pointers, but are type safe.
  • Delegates allow methods to be passed as parameters.
  • Delegates can be used to define callback methods.
  • Delegates can be chained together; for example, multiple methods can be called on a single event.
  • Methods don't need to match the delegate signature exactly.
  • C# version 2.0 introduces the concept of Anonymous Methods, which permit code blocks to be passed as parameters in place of a separately defined method.

Delegate types are derived from the Delegate class in the .NET Framework. Delegate types are sealed—they cannot be derived from— and it is not possible to derive custom classes from Delegate. Because the instantiated delegate is an object, it can be passed as a parameter, or assigned to a property. This allows a method to accept a delegate as a parameter, and call the delegate at some later time. This is known as an asynchronous callback, and is a common method of notifying a caller when a long process has completed. When a delegate is used in this fashion, the code using the delegate does not need any knowledge of the implementation of the method being used.

C# provides support for Delegates through the class called Delegate in the System namespace. Delegates are of two types.

  • Single-cast delegates
  • Multi-cast delegates

A Single-cast delegate is one that can refer to a single method whereas a Multi-cast delegate can refer to and eventually fire off multiple methods that have the same signature.A delegate is either public or internal if no specifier is included in its signature.

public delegate void MyDelegate(string msg);

The return type of the delegate shown in the above example is "void" and it accepts a string argument. The keyword "delegate" identifies this as a delegate to a method. This delegate can refer to and eventually invoke a method that can accept a string argument and has a return type of void. You can use a delegate to make it refer to and invoke a method that has identical signature as the delegate. Even if you are using multi-cast delegates, you can use your delegate to refer to and then fire off multiple methods that have identical signatures.

A delegate should always be instantiated before it is used. The following statement how we can instantiate a delegate.

MyDelegate t = new MyDelegate(show);

This section illustrates how we can implement and use single-cast delegates in C#.

using System;

namespace Delegates
{
    public delegate int MyDelegate(int x, int y);

    public class MyClass
    {
        public static int Add(int x, int y)
        {
            return x + y;

        }

        public static int Multiply(int x, int y)
        {
            return x * y;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //create an instance of MyDelegate
            MyDelegate delegate1 = new MyDelegate(MyClass.Add);

            //Invoke Add method using the delegate;
            int AddResult = delegate1(4, 6);
            Console.WriteLine("4 + 6 = {0}\n", AddResult);

            //create an instance of MyDelegate
            MyDelegate delegate2 = new MyDelegate(MyClass.Multiply);

            //Invoke Multiply method using the delegate;
            int MultiplyResult = delegate2(4, 6);
            Console.WriteLine("4 * 6 = {0}\n", MultiplyResult);

        }
    }
}

During Multicast Delegate's, a delegate object can maintain a list of methods to call, rather than a single method. If you want to add a method to the invocation list of a delegate object , you simply make use of the overloaded += operator, and if you want to remove a method from the invocation list you make use of the overloaded operator -=. If you want to create a multicast delegate with return type you will get the return type of the last method in the invocation list.

using System;

namespace Delegates
{
    public delegate void MyMultiDelegate(int x, int y);

    public class MyClass
    {
        public static void Add(int x, int y)
        {
            Console.WriteLine("4 + 6 = {0}\n", x + y);

        }

        public static void Multiply(int x, int y)
        {
            Console.WriteLine("4 * 6 = {0}\n", x * y );
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //create an instance of MyDelegate that points
            // to the Add method.
            MyMultiDelegate Multidelegate = new MyMultiDelegate(MyClass.Add);

            //using the same instance of MulticastDelegate
            //to call MyClass.Multibly() by adding it to it's 
            //invocation list.
            Multidelegate += new MyMultiDelegate(MyClass.Multiply);

            // This call both Add and Multiply methods
            Multidelegate(4, 6);

            //removing the Add() method from the invocation list
            Multidelegate -= new MyMultiDelegate(MyClass.Add);

            // This call onlly Multiply method
            Multidelegate(4, 6);

        }
    }
}

Reference Articles