Delegates in .NET

A delegate is a reference type and a type-safe function pointer that references methods using their memory addresses and invokes them dynamically at the run time of the program. A delegate has a specified set of parameters and a return type like a method and it invokes a method that has the matching parameters and a return type. It means that the parameters and the return type of a delegate must be the same as the parameters and the return type of a method it references to.

An instance of a delegate takes a method as a parameter and references it using its memory address. To invoke a method using a delegate, first we define a custom delegate reference type using the delegate keyword and declare its parameters list and a return type depending on the target method then we declare an instance from it and instantiate it by assigning the target method to it as parameter. When a method is assigned as a parameter to an instance of the delegate reference type, it stores the memory address of that method and invokes it dynamically during runtime of the program.

An instance of the delegate invokes either a static method associated with a class or an instance method associated with an object. A delegate reference type is similar to other reference types but the main difference is that other reference types hold the references or the memory addresses of variables and a delegate reference type holds the reference or the memory address of a method like a function pointer in the C++ programming language.

A delegate is similar to function pointers in the C++ programming language. Function pointers of the C++ programming language are a pointer variable that points to a function using its memory address. To invoke a function using a function pointer, we simply assign the memory address of the method to the function pointer variable and invoke it using its memory address. A function pointer variable in C++ is a pointer variable but its declaration is similar to the function declaration that has the matching parameters list and a return type with the parameters list and the return type of the function that points to it. Therefore, a function pointer variable in C++ programming invokes a function that has the matching parameters a return type.

The main difference between the C++ function pointers and the delegates is that the C++ function pointer holds only the memory address of a function and it does not carry any additional information such as the number of parameters used by the function, the types of the parameters and the return type of the function while a delegate holds the memory address of a method and carries all the information associated with the method we want to invoke and also can access any variable visible to the enclosing scope.

The delegates are actually the .NET implementation of function pointers and they are object-oriented, type safe and secure unlike C++ functions pointers. Therefore, we can say that delegates are the .NET reference objects that can be used to invoke methods of matching signatures and return type. A delegate invokes a method synchronously and asynchronously and it can also be used to define callback methods. A callback method is a user-defined method that is used to process the result of an asynchronous operation in a separate thread.

Invoke Methods using Delegates

To invoke a method using a delegate we must use the following three steps:

  1. Declare a Delegate Type
  2. Instantiate a Delegate Instance
  3. Invoke the Method

The Declaration of Delegate Type

The declaration of the delegate defines a custom delegate reference type using a keyword delegate. A delegate reference type has a specified set of parameters and a return type depending on the method it references to. A delegate reference type can be declared within the scope of a namespace or within the scope of a class. We cannot declare a delegate as a data member of a class and we cannot declare it as a local variable within the scope of a method because the declaration of a delegate is actually a new type definition and types can be defined only within the scope of a namespace and within the scope of a class. We cannot define any type within the scope of a method. The following is the general syntax to define a delegate reference type:

C# Syntax

  1. [Modifiers] delegate ReturnType DelegateName([ParameterList]); 

The declaration of a delegate type usually has five parts, such as modifiers, the delegate keyword, return type, the delegate name and a list of parameters. The first part of a delegate declaration is [Modifiers] that indicates an access modifier. The access modifiers are keywords used to specify the declared accessibility of a member or a data type. The main and important access modifiers are public, protected, private and internal modifiers. The second part of the delegate declaration is a delegate keyword. A delegate keyword is a reserved word provided by the .NET Framework that is used to declare a delegate reference type. The third part of the delegate declaration is ReturnType that indicates the return type of the delegate reference type. The return type of the delegate reference type must be the same as the return type of the method we want to invoke. The fourth part of the delegate declaration is the DelegateName that indicates a user-defined name of the delegate reference type we want to declare. The user-defined name of a delegate reference type must follow the variables and methods naming convention of the .NET Framework. The fifth part of the delegate declaration is [ParameterList] that indicates the number of parameters of a delegate reference type. The parameters list of the delegate reference type must be the same as the parameters list of the method we want to invoke.

The Instantiation of Delegate Instances

The instantiation of a delegate instance is a process in which an instance of a delegate is referenced or associated with a method that has the matching parameters and a return type. A method can be referenced or associated with an instance of the delegate by assigning that method to it as parameter. When we define a custom delegate reference type using a delegate keyword then we declare an instance from it and instantiate it by assigning the target method to it as parameter. When the method is assigned as a parameter to an instance of the delegate, it stores the memory address of that method and the method is referenced or associated with it. The following is the general syntax to declare and instantiate an instance of a delegate reference type.

C# Syntax

  1. //Declare an instance of the Delegate reference type  
  2. DelegateName instanceName = null;  
  3.   
  4. //Instantiate an instance of the Delegate reference type  
  5. instanceName = new DelegateName(MethodName) 

The preceding declaration declares and instantiates an instance of the delegate reference type. The name of the declared instance is instanceName. The DelegateName indicates the name of the delegate reference type from that we declare an instance instanceName. The new keyword is used to instantiate the instance of the delegate. The MethodName represents the name of the method to be invoked by the delegate.

The Invocation of Methods

When a method is referenced or associated with an instance of the delegate then this is the last step in which we invoke that method by calling the associated instance of the delegate and assign values to its parameters, if the referenced or associated method takes parameters. The following is the general syntax to invoke a method using the referenced or associated delegate instance.

C# Syntax

  1. ReturnType instanceName(ParametersList); 

In the preceding declaration the ReturnType represents the return type of the referenced or associated method, the instanceName represents the name of the delegate instance and the ParametersList represents the number of parameters of the referenced or associated method.

Types of Delegates

The delegates are categorized into the following two types:

  • Single Cast Delegates
  • Multicast Delegates

Single Cast Delegates

A single cast delegate is a type of delegate that references to a single method at a time. A single cast delegate holds the reference or the memory address of a single method that has the matching parameters and a return type. The following is an example of a single cast delegate type definition.

C# Example of Delegate type Definition

  1. public delegate int myDelegate(int x); 

The preceding declaration defines a delegate reference type myDelegate. The myDelegate is a user-defined name of the delegate that takes a single integer parameter and returns an integer value. Therefore, the myDelegate references and invokes a method that takes a single integer parameter and returns an integer value.

Program # 1

Write a program that invokes a simple static method using a delegate and displays a message in the method body. The method has no parameters list and no return type.

C# Program

  1. using System;  
  2. namespace ProgramNamespace  
  3. {  
  4.    //Define a Delegate type that has no parameters list and no return //type  
  5.    public delegate void dlgMessage();  
  6.   
  7.    public class MainProgramClass  
  8.    {  
  9.       static void Main(string[] args)  
  10.       {  
  11.          //Declare an instance of the delegate reference type dlgMessage  
  12.          dlgMessage instDelegate = null;  
  13.   
  14.          //Instantiate the delegate instance insDelegate by assigning a //method  
  15.          instDelegate = new dlgMessage(displayMessage);  
  16.   
  17.          //Invoke the method displayMessage() using the delegate instance //instDelegate  
  18.   
  19.          instDelegate();  
  20.   
  21.          Console.WriteLine("Press any key to exit program");  
  22.          Console.ReadKey();  
  23.       }  
  24.   
  25.       //Declare a method that has no parameters and no return type and //display a message  
  26.   
  27.       public static void displayMessage()  
  28.       {  
  29.          Console.WriteLine("Welcome to the .NET Delegates");  
  30.       }  
  31.    }  

Program # 2

Write a program that invokes a non-static method of a class using a delegate. The method has no parameters list and it return a string message to its calling point.

C# Program

  1. using System;  
  2.   
  3. namespace MainProgramNamespace  
  4. {  
  5.    //Define a Delegate type that has no parameters list and returns a //string  
  6.    public delegate string dlgMessage();  
  7.   
  8.    //Declare a class that contains a single non static method. The //method has no parameters
        list and returns a string message to its //calling point
      
  9.   
  10.    public class MyMethodClass  
  11.    {  
  12.       //Declare a non static method that has no parameters list and //returns a string message to its calling point  
  13.   
  14.       public string displayMessage()  
  15.       {  
  16.          return "Welcome to the .NET Delegates";  
  17.       }  
  18.    }  
  19.   
  20.    public class MainProgramClass  
  21.    {  
  22.       static void Main(string[] args)  
  23.       {  
  24.          //Declare an instance of the class MyMethodClass  
  25.          MyMethodClass obj = new MyMethodClass();  
  26.   
  27.          //Declare an instance of the delegate reference type dlgMessage  
  28.          dlgMessage instDelegate = null;  
  29.   
  30.          //Instantiate the delegate instance insDelegate by assigning the //non static method
              displayMessage() of the class MyClass
      
  31.   
  32.          instDelegate = new dlgMessage(obj.displayMessage);  
  33.   
  34.          //Invoke the method displayMessage() using the delegate instance //instDelegate and
              declare a string variable that holds the return //value of the displayMessage() method
      
  35.   
  36.          string msg = instDelegate();  
  37.   
  38.          //Display the message  
  39.          Console.WriteLine(msg);  
  40.   
  41.          Console.WriteLine("Press any key to exit program");  
  42.          Console.ReadKey();  
  43.       }  
  44.    }  

The preceding program displays a message “Welcome to the .NET Delegates”. The program contains a delegate reference type dlgMessage and a method displayMessage. The delegate dlgMessage is a parameter-less delegate that does not take parameters and its return type is a string that returns a string value. The method displayMessage is a parameter-less user-defined method that is declared in a class MyMethodClass. The method displayMessage returns a string “Welcome to the .NET Delegates”. In the main method of the program we declared an instance of the delegate instDelegate. The parameters and the return types of the delegate dlgDelegate and the parameters and return type of the method displayMessage are the same. Therefore, the instance of the delegate instDelegate references and invokes the method displayMessage and displays a string message “Welcome to the .NET Delegates” on the screen.

Program # 3

Write a program that invokes a non-static method of a class using a delegate. The method takes two integer parameters and returns their sum to its calling point.

C# Program

  1. using System;  
  2.   
  3. namespace ProgramNamespace  
  4. {  
  5.    //Define a Delegate reference type that takes two integer //parameters and returns an integer value  
  6.   
  7.    public delegate int calculateTwoValues(int x, int y);  
  8.   
  9.    //Declare a class that contains a single non static method. The //method has two integer parameters and
       returns their sum to its
      
  10.    //calling point  
  11.   
  12.    public class MyMethodClass  
  13.    {  
  14.       //Declare a non static method that takes two integer parameters //and returns their sum to its calling point  
  15.   
  16.       public int addValues(int x, int y)  
  17.       {  
  18.          return (x + y);  
  19.       }  
  20.    }  
  21.    public class MainProgramClass  
  22.    {  
  23.       static void Main(string[] args)  
  24.       {  
  25.          //Declare an instance of the class MyMethodClass  
  26.          MyMethodClass obj = new MyMethodClass();  
  27.   
  28.          //Declare an instance of the delegate reference type  
  29.          calculateTwoValues instDelegate = null;  
  30.   
  31.          //Instantiate the delegate instance insDelegate by assigning the //non static method addValues()
              of the class MyMethodClass
      
  32.   
  33.          instDelegate = new calculateTwoValues(obj.addValues);  
  34.   
  35.          //Invoke the method addValues() using the delegate instance //instDelegate and declare an integer
              variable that holds the return
      
  36.          //value of the addValues() method  
  37.   
  38.          int sumValue = instDelegate(10, 20);  
  39.   
  40.          //Display the result of the addValues() method  
  41.          Console.WriteLine(sumValue);  
  42.   
  43.          Console.WriteLine("Press any key to exit program");  
  44.          Console.ReadKey();  
  45.       }  
  46.    }  

The preceding program calculates the sum of two integer values and displays their result. The program contains a delegate reference type calculateTwoValues and a method addValues that is defined in a class MyMethodClass. The delegate calculateTwoValues takes two integer parameters and returns an integer value. The method addValues also takes two integer parameters and returns an integer value. The parameters and the return type of the delegate calculateTwoValues and the parameters and return type of the method addValues are the same. In the main method of the program we declared an instance of the delegate reference type instDelegate. The instance instDelegate takes two integer values from the main method of the program and invokes the method addValues. The method addValues calculates the sum of the two received values and returns the result back to the main method of the program. In the main method of the program we declared an integer variable that stores the result of the method.

The Multicast Delegates

A multicast delegate is a type of the delegate that references and invokes multiple methods at the same time. An instance of the multicast delegate reference type holds the references or the memory addresses of multiple methods that have the same parameters lists and the same return types as the parameters list and the return type of that of the delegate reference type. It means that the methods we want to invoke using a multicast delegate must have matching parameters and return types with the delegate reference type.

The declaration of a multicast delegate and a single cast delegate is the same but the main difference is that an instance of a single cast delegate reference type references and invokes a single method at a time whereas an instance of a multicast delegate reference type references and invokes multiple methods at the same time. The multicast delegate reference type is derived from the MulticastDelegate class that represents a multicast delegate type. The multicast delegate provides two operators, the += operator and -= operator, that are used to add to and remove from the reference of a method, respectively, of the instance of the multicast delegate reference type. The multicast delegate holds the reference of a methods with a += operator and removes the reference of a method with -= operator. The following is an example of a multicast delegate type definition.

C# Example of Delegate type Definition

public delegate void myDelegate(int x);

The preceding declaration defines a delegate type myDelegate. The myDelegate is a user-defined name of the delegate that takes a single integer parameter and its return type is void that does not return any value. The delegate myDelegate is a multicast delegate type that references and invokes multiple methods at the same time.

Program # 4

Write a program that invokes multiple methods using a multicast delegate. Declare three instance methods in a class and invoke these methods using a delegate from the main method of the program. The first method takes two integer values and returns their sum back to the main method, the second method takes two integer values and returns their difference back to the main method of the program and the third method takes two integer values and returns their multiplication to the main method of the program.

C# Program

  1. using System;  
  2.   
  3. namespace ProgramNamespace  
  4. {  
  5.   
  6.    //Define a Multicast delegate reference type that takes two integer //parameters  
  7.    public delegate void calculateTwoValues(int x, int y);  
  8.   
  9.    //Declare a class that contains three user-defined methods  
  10.   
  11.    public class MyMethodClass  
  12.    {  
  13.       public void AddValues(int x, int y)  
  14.       {  
  15.          Console.WriteLine("The sum of two values is");  
  16.          Console.WriteLine(x + y);  
  17.       }  
  18.   
  19.       public void SubtractValues(int x, int y)  
  20.       {  
  21.          Console.WriteLine("The subtraction of two values is");  
  22.          Console.WriteLine(x - y);  
  23.       }  
  24.   
  25.       public void MultiplyValues(int x, int y)  
  26.       {  
  27.          Console.WriteLine("The multiplication of two values is");  
  28.          Console.WriteLine(x * y);  
  29.       }  
  30.    }  
  31.   
  32.    public class MainProgramClass  
  33.    {  
  34.       public static void Main()  
  35.       {  
  36.          //Declare an instance of the class MyMethodClass  
  37.          MyMethodClass obj = new MyMethodClass();  
  38.   
  39.          //Declare an instance of the delegate reference type  
  40.          calculateTwoValues instDelegate = null;  
  41.   
  42.          //Instantiate the multicast delegate using multiple methods  
  43.          instDelegate += new calculateTwoValues(obj.AddValues);  
  44.          instDelegate += new calculateTwoValues(obj.SubtractValues);  
  45.          instDelegate += new calculateTwoValues(obj.MultiplyValues);  
  46.   
  47.          //Invoke the multiple methods using the instance of the multicast //delegate and pass two
                integer values to all methods
      
  48.          instDelegate(5, 2);  
  49.   
  50.          Console.WriteLine("Press any key to exit program");  
  51.          Console.ReadKey();  
  52.       }  
  53.    }