English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Delegado de C# (Delegate)

¿Qué hacer si queremos pasar una función como parámetro? ¿Cómo maneja C# las funciones de devolución o los gestores de eventos? La respuesta es-delegado (Delegate). El delegado (Delegate) es una variable de tipo de datos de referencia que contiene una referencia a un método. La referencia se puede cambiar en tiempo de ejecución.

Los delegados sonDefinir la firma del métodode tipo de datos de referencia. Puede definir variables de delegado, al igual que con otros tipos de datos, que pueden referirse a cualquier método que tenga la misma firma que el delegado.

Trabajar con delegados implica tres pasos:

  1. Declaración de delegados

  2. Establecer el método de destino

  3. Llamar al delegado

Se puede declarar un delegado utilizando la palabra clave delegate y la firma de la función, como se muestra a continuación.

  Sintaxis de delegado

[modificador de acceso] delegate [tipo de retorno] [nombre del delegado]([parámetros])

A continuación, se declaró un delegado llamado MyDelegate.

public delegate void MyDelegate(string msg);

Above, we declared a MyDelegate withvoidTipo de retorno y parámetro de cadena. Los delegados se pueden declarar tanto en el exterior como en el interior de una clase. En realidad, debería declararse fuera de la clase.

Después de declarar el delegado, necesitamos establecer el método de destino o la expresión lambda. Podemos lograr esto creando un objeto del delegado utilizando la palabra clave new y pasando un método que coincida con la firma del delegado.

public delegate void MyDelegate(string msg); // Declaración de delegados
//Establecer el método de destino
MyDelegate del = new MyDelegate(MethodA);
// o
MyDelegate del = MethodA; 
// o expresión lambda 
MyDelegate del = (string msg) => Console.WriteLine(msg);
// Método de destino
static void MethodA(string message)
{
    Console.WriteLine(message);
}

Puede configurar directamente el método de destino sin crear un objeto de delegado, por ejemplo, MyDelegate del = MethodA.

Después de configurar el método de destino, se puede llamar al delegado utilizando el método Invoke() o utilizando el operador ().

del.Invoke("Hello World!");
//o 
del("Hello World!");

A continuación, se muestra un ejemplo completo del delegado.

public delegate void MyDelegate(string msg); //Declaración de delegados
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del = ClassA.MethodA;
        del("Hello World");
        del = ClassB.MethodB;
        del("Hello World");
        del = (string msg) => Console.WriteLine("Llamado a la expresión lambda: ") + msg);
        del("Hello World");
    }
}
class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("Llamado al método MethodA() de ClassA con parámetro: ") + message);
    }
}
class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("Llamado al método MethodB() de ClassB con parámetro: ") + message);
    }
}

La siguiente imagen ilustra el delegado.

Delegados de C#

Pasar el delegado como parámetro

Los métodos pueden tener parámetros de tipo delegado, como se muestra a continuación.

public delegate void MyDelegate(string msg); //Declaración de delegados
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del = ClassA.MethodA;
        InvokeDelegate(del);
        del = ClassB.MethodB;
        InvokeDelegate(del);
        del = (string msg) => Console.WriteLine("Llamado a la expresión lambda: ") + msg);
        InvokeDelegate(del);
    }
    static void InvokeDelegate(MyDelegate del) // Parámetros del tipo MyDelegate
    {
        del("Hello World");
    }
}
class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("Llamado al método MethodA() de ClassA con parámetro: ") + message);
    }
}
class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("Llamado al método MethodB() de ClassB con parámetro: ") + message);
    }
}

En .NET, los tipos Func y Action son delegados genéricos integrados, que deben usarse para los delegados más comunes, en lugar de crear nuevos delegados personalizados.

Delegado de multicast

Un delegado puede apuntar a varios métodos. Un delegado que apunta a varios métodos se llama delegado de multicast.+” o “+El operador = agrega la función a la lista de llamadas, mientras que "-" y "-El operador = lo elimina.

public delegate void MyDelegate(string msg); //Declaración de delegado
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del1 = ClassA.MethodA;
        MyDelegate del2 = ClassB.MethodB;
        MyDelegate del = del1 + del2; // del1 + del2
        del("Hello World");
        MyDelegate del3 = (string msg) => Console.WriteLine("Llamado a la expresión lambda: ") + msg);
        del += del3; // del1 + del2 + del3
        del("Hello World");
        del = del - del2; // Eliminar del2
        del("Hello World");
        del -= del1 // Eliminar del1
        del("Hello World");
    }
}
class ClassA
{
    static void MethodA(string message)
    {
        Console.WriteLine("Llamado al método MethodA() de ClassA con parámetro: ") + message);
    }
}
class ClassB
{
    static void MethodB(string message)
    {
        Console.WriteLine("Llamado al método MethodB() de ClassB con parámetro: ") + message);
    }
}

Los operadores de suma y resta siempre trabajan como parte de una asignación: del1+=del2; como del1=del1+del2Equivalente completo; también es así con la resta.

Si el delegado devuelve un valor, entonces cuando se llama al delegado de multicast, se devolverá el valor asignado por última vez al método de destino.

public delegate int MyDelegate(); //Declaración de delegados
class Program
{
    static void Main(string[] args)
    {
        MyDelegate del1 = ClassA.MethodA;
        MyDelegate del2 = ClassB.MethodB;
        MyDelegate del = del1 + del2; 
        Console.WriteLine(del());// Retorno200
    }
}
class ClassA
{
    static int MethodA()
    {
        return 100;
    }
}
class ClassB
{
    static int MethodB()
    {
        return 200;
    }
}

Delegados genéricos

Se puede definir un delegado genérico de la misma manera que un delegado, pero se puede usar un parámetro de tipo genérico o tipo de retorno. Al establecer el método de destino, debe especificar el tipo genérico.

Por ejemplo, vea el delegado genérico utilizado para parámetros int y string.

public delegate T add<T>(T param1, T param2; // Delegados genéricos
class Program
{
    static void Main(string[] args)
    {
        add<int> sum = Sum;
        Console.WriteLine(sum(10, 20));
        add<string> con = Concat;
        Console.WriteLine(conct("Hello ", "World!!"));
    }
    public static int Sum(int val1, int val2)
    {
        return val1 + val2;
    }
    public static string Concat(string str1, string str2)
    {
        return str1 + str2;
    }
}

Los delegados también se utilizan para declarar eventos y métodos anónimos.

 Puntos a recordar

  1. Un delegado es un tipo de datos de referencia que define una firma.

  2. Un variable de tipo de delegado puede referirse a cualquier método que tenga la misma firma que el delegado.

  3. Sintaxis:[Accesador de acceso] delegado [tipo de retorno] [nombre del delegado]([parámetros])([access modifier] delegate [return type] [delegate name]([parameters]))

  4. La firma del método de destino debe coincidir con la firma del delegado.

  5. El delegado se puede llamar como una función común o método invoke().

  6. Se puede usar “ +” o “ + El operador = asigna varios métodos al delegado y utiliza “-” o “-El operador = lo elimina. Se llama delegado de multicast.

  7. Si el delegado de multicast devuelve un valor, devuelve ese valor del último método de destino asignado.

  8. El delegado se utiliza para declarar eventos y métodos anónimos en C#.