THE DELEGATE

C sharpC Sharp delegates are a new type after classes, structs and interfaces. It is a reference type whose instances allow us to treat methods as if they were objects. A delegate has no implementation, it can be defined at the namespace level but also at the class level. Let’s see how a delegate declares.

namespace Delegate

{

     public delegate int MyDelegate(int a, int b);

}

As you can see a delegate declares itself with the keyword delegate, otherwise it looks like the definition of a method, we have declared an int return type and two integer type parameters a and b. It is a bit like a method declared within an interface, the peculiarity is that in the declaration there is the keyword delegate. This particular delegate represents any method that takes two integers as input and returns an int.

USE OF DELEGATES

using System;
namespace Delegate
{
    public delegate int MyDelegate(int a, int b);
    class Program
    {
        static void Main(string[] args)
        {
            MyDelegate md = Somma;//FIRST FORM OF INITIALIZATION OF THE DELEGATE
            //MyDelegate md1 = new MyDelegate(Somma);SECOND FORM TO INITIALIZE A DELEGATE. LESS COMMON.
            int result = md(10,5);
            Console.WriteLine($"Somma: {result}");
            md=Differenza;
            result = md(10,5);
            Console.WriteLine($"Differenza: {result}");
            md=Moltiplicazione;
            result = md.Invoke(10,5);//THE Invoke METHOD CAN ALSO BE USED TO CALL THE METHOD.
            Console.WriteLine($"Moltiplicazione: {result}");
            
            static int Somma(int arg1, int arg2)
            {
                return arg1+arg2;
            }
            static int Differenza(int arg1, int arg2)
            {
                return arg1 - arg2;
            }
            static int Moltiplicazione(int arg1, int arg2)
            {
                return arg1 * arg2;
            }
        }
    }
}

As you can see I have stated three methods Somma, Differenza and Moltiplicazione each having the same signature as the delegate. With the instruction:

MyDelegate md = Somma;

I initialized the instance variable of the delegate with the Somma method, the invocation of this method takes place with the instruction:

int result = md(10,5); or

int result = md.Invoke(10,5);

Once the sum has been made, the same delegate instance can point to a new method. I used the word point because those familiar with the C or C ++ language may observe that a delegate is similar to a function pointer, the problem with pointers is that they often cause bugs that are difficult to find. C# instead provides us with a more transparent mechanism and certainly less prone to bugs.

I DELEGATES IN C SHARP I DELEGATES MULTICAST

Let’s try to clarify some aspects before introducing the code for a multicast delegate. This type of delegate or rather the instance variable of the delegate is initialized as already seen. With the += operator, multiple methods are assigned to the instance created, at the time of invocation the methods will be executed in cascade. Let’s see two implications to know:

  • If the delegate returns a value then only the value of the last executed method will be returned when the multicast delegate is invoked. Therefore multicast delegates should be used except for rare exceptions with the return type void.
  • If an exception is thrown in one of the methods, the invocation chain is interrupted.
using System;
namespace Delegate
{
    public delegate void MyDelegate(int a, int b);
    class Program
    {
        static void Main(string[] args)
        {
            MyDelegate md = Somma;
            md += Differenza;
            md+=Moltiplicazione;
            md.Invoke(10,5);
            
            static void Somma(int arg1, int arg2)
            {
                 Console.WriteLine($"Somma: {arg1 + arg2}");
            }
            static void Differenza(int arg1, int arg2)
            {
                Console.WriteLine($"Differenza: {arg1 - arg2}");
            }
            static void Moltiplicazione(int arg1, int arg2)
            {
               Console.WriteLine($"Moltiplicazione: {arg1 * arg2}");
            }
        }
    }
}

THE DELEGATES IN C SHARP THE GENERIC DELEGATES

using System;
namespace Delegate
{
    public delegate void MyDelegate<T>(T a, T b) where T:struct;
    class Program
    {
        static void Main(string[] args)
        {
            MyDelegate<int> md1 = Somma;
            MyDelegate<double> md2 = Differenza;
            MyDelegate<float> md3 = Moltiplicazione;
            md1.Invoke(12,7);
            md2.Invoke(100.45,90.78);
            md3.Invoke(12.8f, 13.4f);            
            static void Somma(int arg1, int arg2)
            {
                 Console.WriteLine($"Somma: {arg1 + arg2}");
            }
            static void Differenza(double arg1, double arg2)
            {
                Console.WriteLine($"Differenza: {arg1 - arg2}");
            }
            static void Moltiplicazione(float arg1, float arg2)
            {
               Console.WriteLine($"Moltiplicazione: {arg1 * arg2}");
            }
        }
    }
}

DELEGATES DEFAULT ACTION AND FUNC

.NET Framework provides us with two predefined delegates Action and Func. The difference between the two is that Action returns no values, so the return value is void and can accept up to 16 type parameters. The Func delegate vice versa we use it when we need a return value. Let’s see what these two default delegates look like.

public delegate void Action();

public delegate void Action(T arg);

public delegate void Action<T1,T2>(T1 arg1, T2 arg2);

public delegate TResult Func();

public delegate TResult Func<T1, TResult>(T1 arg);

public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);

using System;
namespace Delegate
{
    class Program
    {
        static void Main(string[] args)
        {
            Action<int,double> myAction = Somma;
            myAction+=Differenza;
            myAction+=Moltiplicazione;
            myAction.Invoke(10,89.98);            
            static void Somma(int arg1, double arg2)
            {
                 Console.WriteLine($"Sum: {arg1 + arg2}");
            }
            static void Differenza(int arg1, double arg2)
            {
                Console.WriteLine($"Difference: {arg1 - arg2}");
            }
            static void Moltiplicazione(int arg1, double arg2)
            {
               Console.WriteLine($"Multiplication: {arg1 * arg2}");
            }
            Func<double,double> MyFunc = RadiceQuadrata;
            double result = MyFunc.Invoke(144);
            Console.WriteLine(result);
            static double RadiceQuadrata(double arg1)
            {
                return Math.Sqrt(arg1);
            }
        }
    }
}

IN-DEPTH DISCUSSION OF DELEGATES

In C#, a delegate is a type that represents references to methods with a particular signature and return type. It is similar to a function pointer in C++, but is type- and environment-safe. Delegates are used to pass methods as parameters to another function. This feature is particularly useful for event-oriented programming and for implementing callbacks.

Here is a more detailed description and example of using delegates in C#:

Key features of delegates:

1. Method Signature: A delegate can only refer to methods that have a matching signature (i.e., same return type and same parameters).

2. Multicast: Delegates can be concatenated together; that is, they can refer to multiple methods simultaneously. When a multicast delegate is invoked, all methods associated with it are called sequentially.

3. Type Safe: Delegates are type safe, which means that the compiler checks the types of methods assigned to delegates, preventing type errors.

Defining and Using a Delegate:

Defining a Delegate.

// Definizione di un delegato
public delegate void MyDelegate(string message);

Statement of Delegate Compatible Methods.

// Metodo compatibile con il delegato
public void Method1(string message)
{
      Console.WriteLine(“Method1: ” + message);
}

public void Method2(string message)
{
      Console.WriteLine(“Method2: ” + message);
}

Assignment of Methods to Delegate.

// Creazione di un’istanza del delegato e assegnazione dei metodi
MyDelegate del = new MyDelegate(Method1);
del += Method2; // Aggiunta di un altro metodo al delegato (multicast)

// Invocazione del delegato
del(“Hello, World!“);

// Output:
// Method1: Hello, World!
// Method2: Hello, World!

LINKS TO PREVIOUS POST

LINK TO THE CODE ON GITHUB