Delegates in C#

 

1 - What is a delegate

We can say that a delegate is a reference to a method.

When we define a delegate, we are declaring a variable that points to another method. 

We can define a delegate using the delegate keyword followed by the function declaration as shown below:

<access modifier> delegate <return type> <name>(<parameters>[]);

Which can be translated to the following code:

public delegate void ImprimirDelegado(string value);

1.1 - Delegate example

Now it's time for a little example:

We have the following code:

namespace PA.Delegates
{
    public delegate void ImprimirDelegado(string value);
    public class EjemploDelegado
    {
        private void Imprimir(string valor)
        {
            Console.WriteLine(valor);
        }

        public void EjemploDelegate()
        {
            //Declaration
            ImprimirDelegado imprimirDelegado = new ImprimirDelegado(Imprimir);

            //invocation
            imprimirDelegado("texto de ejemplo");
        }

    }
}

We should pay attention to several points:

  • First, the delegate can be outside the class, although it can also be inside.
  • Then there's a class containing:
    • A method called "Imprimir" that has the same input type and return type as the delegate.
    • A main method which declares the delegate and passes the "Imprimir" method we just created as a parameter.
      • Invoking the delegate, passing text as parameter. 

It is important to keep in mind that the return type and the parameters of the method must match between the method and the delegate. Otherwise, we will get a compilation error. 

 

2 - Working with delegates and generics

The example we just saw is very simple and serves as an introduction, but before moving further, it must be noted that delegates can also work with generics. 

If you are not clear about generics concepts, it is advisable to review this link about generics in C#.

First, we modify the value to accept generics.

public delegate void ImprimirDelegado<T>(T value);

And then we do the same with the method. In this case, we will create two methods. 

The one we already have, and one that accepts an int as parameter. 

And when we declare it, we only need to indicate the type it will store: 

public class EjemploDelegado
{
    private void Imprimir(string valor)
    {
        Console.WriteLine(valor);
    }

    private void Imprimir(int valor)
    {
        Console.WriteLine($"el valor es {valor}");
    }

    public void EjemploDelegate()
    {
        //Declaration
        ImprimirDelegado<string> imprimirDelegado = new ImprimirDelegado<string>(Imprimir);
        ImprimirDelegado<int> imprimirDelegadoEntero = new ImprimirDelegado<int>(Imprimir);

        //invocation
        imprimirDelegado("texto de ejemplo");
        imprimirDelegadoEntero(25);
    }

}

Within .NET there are several delegate types already implemented that are used almost every day. These are Func, Action, and Predicate.

 

3 - Action<T> Delegate

An Action delegate points to a method that returns void. The Action<T> delegates always return void, but they can have 0 to 16 parameters. The types of these parameters are determined by the generic types.

For example: an Action<string> is a method that returns void but requires a string as input. 

Which is exactly the Imprimir method we've already implemented.

So, we can assign this method to Action<string> and then invoke it.

private void Imprimir(string valor)
{
    Console.WriteLine(valor);
}

public void EjemploAction()
{
    Action<string> imprimirAction = Imprimir;
    imprimirAction("ejemplo");
}

 

3.1 - Anonymous delegate methods

Very similar to what we know as anonymous types, we have anonymous methods.

When we define an Action, we can directly assign the value of the delegate it references:

public void EjemploActionAnonimo()
{
    Action<string> imprimirAction = delegate (string valor)
    {
        Console.WriteLine(valor);
    };

    imprimirAction("ejemplo");
}

This code can be improved with a lambda expression which we will discuss later:

Action<string> imprimirAction = v => Console.WriteLine(v);

As mentioned, we will cover this in more detail later. 

 

4 - Func<in T, out TResult> Delegate 

Similar to the previous case, it accepts 1 to 16 parameters and their types are generic. The difference is that in this case, Func<in T, out TResult> must return a value, and the last type passed to Func is the return type. 

In other words, a Func<int, string> is a function that takes an int and returns a string:

Func<int, string> resultado = v => $"el resultado es{v}";
Console.WriteLine(resultado(5));

As noted, it accepts multiple parameters, for example, if we do a multiplication. 

Func<int, int, int> multiplicacion = (v1, v2) => v1 * v2;
int valor = multiplicacion(3, 2);
Console.WriteLine($"El resultado es {valor}");

 

5 - Predicate<T> Delegate

Similar to the previous two, in this case, a Predicate ALWAYS returns a boolean. For example, Predicate<int> takes an int and returns a boolean.

Predicate<int> mayorDeEdad = e => e >= 18;
bool esMayorDeEdad = mayorDeEdad(10);

 

Conclusion

In this post, we have seen how to instantiate a delegate and how to use the Func, Action, and Predicate delegates. Having a clear understanding of delegates is extremely useful

We will use delegates every day, which will help us write cleaner and higher-quality code. 

But not only that, when we use LINQ, we are constantly using Func<T>.

This post was translated from Spanish. You can see the original one here.
If there is any problem you can add a comment bellow or contact me in the website's contact form

Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2025 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café