Crear una instancia e invocar tipos de delegado

Completado

Los tipos delegados se implementan mediante el siguiente proceso:

  1. Declare el delegado: Defina un tipo de delegado con una firma específica, que incluye el tipo de valor devuelto y los parámetros.
  2. Crear una instancia del delegado: Cree una instancia del tipo delegado y especifique el método al que se va a llamar.
  3. Invoque el delegado: Llame a la instancia del delegado y pase los argumentos necesarios.

Una vez que se haya declarado un delegado nombrado, puede crear instancias de ese tipo de delegado y usarlas para llamar a métodos que coincidan con la firma del delegado. Cada instancia de delegado puede apuntar a un método diferente, lo que permite la invocación de método flexible y dinámico. Además, los delegados se pueden combinar para crear delegados de multidifusión, que permiten invocar varios métodos en una sola llamada.

Cuando se invoca un delegado, llama a los métodos a los que apunta, pasando los argumentos especificados en la firma del delegado.

Crear una instancia e invocar delegados

Los delegados pueden instanciarse mediante métodos con nombre, conversión de grupos de métodos, métodos anónimos o expresiones lambda. La elección del método de creación de instancias depende del caso de uso específico y del nivel deseado de legibilidad y mantenimiento.

Crear una instancia de delegados con métodos con nombre

Los métodos con nombre se definen con un nombre específico y se pueden reutilizar. El uso de métodos con nombre es útil cuando se desea crear una instancia de delegado que apunte a un método específico. Normalmente, los métodos con nombre se definen en una clase o estructura y pueden ser métodos estáticos o de instancia.


public delegate void Notify(string message);

public class Program
{
    public static void Main()
    {
        // Create an instance of the delegate using a named method
        Notify notify = new Notify(NotificationService.SendNotification);

        // Invoke the delegate
        notify("Hello, World!");
    }
}

public static class NotificationService
{
    // Method that matches the delegate's signature
    public static void SendNotification(string message)
    {
        Console.WriteLine("Notification sent: " + message);
    }
}

En este ejemplo se muestra cómo crear un tipo Notify de delegado que toma un parámetro de cadena y devuelve void. El SendNotification método coincide con la firma del delegado, lo que permite asignarla a la instancia del delegado. Cuando se invoca el delegado, llama al método SendNotification con el mensaje proporcionado.

Crear una instancia de delegados con conversión de grupo de métodos

La conversión de grupos de métodos es una manera abreviada de crear una instancia de delegado haciendo referencia directamente a un método sin crear explícitamente una instancia de delegado. El uso de la conversión de grupos de métodos resulta útil cuando se desea crear una instancia de delegado que apunte a un método específico sin necesidad de un constructor delegado explícito. La conversión del grupo de métodos permite asignar un método directamente a un tipo delegado sin crear explícitamente una instancia de delegado. Esta capacidad es útil cuando la firma del método coincide con la firma del delegado, ya que permite código más limpio y conciso.


public delegate void Notify(string message);

public class Program
{
    public static void Main()
    {
        // Create an instance of the delegate using a method group conversion for a named method
        Notify notifyMethodGroup = NotificationService.SendNotification;

        // Invoke the delegate
        notifyMethodGroup("Hello from Method Group!");

    }
}

public static class NotificationService
{
    // Method that matches the delegate's signature
    public static void SendNotification(string message)
    {
        Console.WriteLine("Notification sent: " + message);
    }
}


En este ejemplo se muestra cómo crear una instancia de delegado mediante una conversión de grupo de métodos. El SendNotification método se asigna directamente a la instancia notifyMethodGroupde delegado , lo que permite invocarlo con un mensaje. Cuando se invoca el delegado, llama al método SendNotification con el mensaje proporcionado.

Crear una instancia de delegados con métodos anónimos

Los métodos anónimos permiten definir un método en línea sin asignarle un nombre explícito. Esta capacidad es útil para las operaciones de corta duración o cuando desea definir el comportamiento directamente en el punto de uso. Los métodos anónimos se pueden usar para crear instancias de delegados sin definir un método independiente. El uso de métodos anónimos permite un código más conciso y puede mejorar la legibilidad en determinados escenarios.


public delegate void Notify(string message);

public class Program
{
    public static void Main()
    {
        // Create an instance of the delegate using an anonymous method
        Notify notifyAnonymous = delegate (string message) { Console.WriteLine("Anonymous notification: " + message); };

        // Invoke the delegate
        notifyAnonymous("Hello from Anonymous Method!");

    }
}

En este ejemplo se muestra cómo crear una instancia de delegado mediante un método anónimo. El método anónimo delegate (string message) { Console.WriteLine("Anonymous notification: " + message); } define el comportamiento del delegado en línea, lo que le permite ser invocado con un mensaje. Cuando se invoca al delegado, ejecuta el código definido en el método anónimo.

Crear una instancia de delegados con expresiones lambda

Las expresiones lambda son una manera concisa de definir métodos anónimos. Permiten crear instancias de delegado sin definir explícitamente un método. Esta capacidad es útil para las operaciones de corta duración o cuando desea definir el comportamiento directamente en el punto de uso.


public delegate void Notify(string message);

public class Program
{
    public static void Main()
    {
        // Create an instance of the delegate using a lambda expression
        Notify notifyLambda = (message) => Console.WriteLine("Lambda notification: " + message);

        // Invoke the delegate
        notifyLambda("Hello from Lambda!");
    }
}

En este ejemplo se muestra cómo crear una instancia de delegado mediante una expresión lambda. La expresión lambda (message) => Console.WriteLine("Lambda notification: " + message) define el comportamiento del delegado en línea, permitiendo invocarlo con un mensaje. Cuando se invoca al delegado, ejecuta el código definido en la expresión lambda.

Invocar delegados de difusión única y multidifusión

Los delegados se pueden invocar como métodos normales. Cuando se invoca un delegado, llama a los métodos a los que apunta, pasando los argumentos especificados en la firma del delegado. La invocación de un delegado es similar a llamar directamente a un método.

Los delegados se pueden combinar para crear delegados de multidifusión, que permiten invocar varios métodos en una sola llamada. La capacidad de multidifusión es útil cuando desea realizar varias acciones, como notificar a varios suscriptores de eventos o ejecutar varios métodos en un orden específico.

Se pueden asignar varios objetos a una instancia de delegado mediante el + operador . El delegado de multidifusión contiene una lista de los delegados asignados. Cuando se llama al delegado de multidifusión, invoca a los delegados de la lista, en orden. Solo se pueden combinar delegados del mismo tipo.

El operador - se puede usar para quitar un delegado de componente de un delegado de multidifusión.

En el ejemplo siguiente se muestra cómo combinar delegados mediante el + operador y quitar un delegado mediante el - operador :


using System;

namespace DelegateExamples;

// Define a custom delegate that has a string parameter and returns void.
delegate void CustomCallback(string s);

class TestClass
{
    // Define two methods that have the same signature as CustomCallback.
    static void Hello(string s)
    {
        Console.WriteLine($"  Hello, {s}!");
    }

    static void Goodbye(string s)
    {
        Console.WriteLine($"  Goodbye, {s}!");
    }

    static void Main()
    {
        // Declare instances of the custom delegate.
        CustomCallback hiDel, byeDel, multiDel, multiMinusHiDel;

        // Initialize the delegate object hiDel that references the
        // method Hello.
        hiDel = Hello;

        // Initialize the delegate object byeDel that references the
        // method Goodbye.
        byeDel = Goodbye;

        // The two delegates, hiDel and byeDel, are combined to
        // form multiDel.
        multiDel = hiDel + byeDel;

        // Remove hiDel from the multicast delegate, leaving byeDel,
        // which calls only the method Goodbye.
        multiMinusHiDel = (multiDel - hiDel)!;

        Console.WriteLine("Invoking delegate hiDel:");
        hiDel("Elize Harmsen");

        Console.WriteLine("Invoking delegate byeDel:");
        byeDel("Mattia Trentini");

        Console.WriteLine("Invoking delegate multiDel:");
        multiDel("Peter Zammit");

        Console.WriteLine("Invoking delegate multiMinusHiDel:");
        multiMinusHiDel("Lennart Kangur");
    }
}

/* Output:
Invoking delegate hiDel:
  Hello, Elize Harmsen!
Invoking delegate byeDel:
  Goodbye, Mattia Trentini!
Invoking delegate multiDel:
  Hello, Peter Zammit!
  Goodbye, Peter Zammit!
Invoking delegate multiMinusHiDel:
  Goodbye, Lennart Kangur!
*/

En este ejemplo se muestra cómo crear un delegado de multidifusión combinado dos delegados (hiDel y byeDel) usando el operador +. El delegado combinado (multiDel) invoca ambos métodos cuando se le llama. El operador - se utiliza para eliminar uno de los delegados del delegado de multidifusión, dejando solo el otro delegado para ser invocado.

La salida muestra los resultados de invocar cada delegado, lo que muestra cómo funciona el delegado de multidifusión.

Escenarios comunes para usar delegados

Los delegados son versátiles y se pueden usar en varios escenarios para mejorar la flexibilidad y el mantenimiento del código. Son útiles en situaciones en las que necesita pasar métodos como parámetros, implementar mecanismos de devolución de llamada o crear controladores de eventos.

Estos son algunos escenarios comunes en los que se usan delegados:

  • Ordenación y filtrado: Los delegados se pueden usar para pasar funciones de comparación a métodos de ordenación y filtrado. Este proceso permite especificar dinámicamente los criterios para ordenar o filtrar una colección de objetos. Por ejemplo, ordenar una lista de clientes bancarios por distintos criterios, como el nombre, el saldo de la cuenta o el identificador de cliente.

  • Métodos de devolución de llamada: Los delegados se suelen usar para implementar métodos de devolución de llamada. Esta funcionalidad es útil en escenarios en los que un método necesita llamar a otro método una vez completada una operación determinada. Por ejemplo, puede usar un delegado para notificar la finalización de una tarea de procesamiento de datos.

  • Programación asincrónica: se utilizan delegados para invocar métodos asincrónicos. Esta funcionalidad es útil para realizar tareas que pueden tardar mucho tiempo en completarse, como las operaciones de E/S de archivos o las solicitudes de red. Los delegados permiten especificar el método al que se llamará una vez finalizada la operación asincrónica.

  • Control de eventos: los delegados son la base de los eventos en C#. Permiten definir controladores de eventos que se pueden invocar cuando se produce un evento. Por ejemplo, en una aplicación bancaria, puede usar delegados para notificar a los clientes cuando se completa una transacción.

  • Implementación de patrones de diseño: Los delegados se utilizan en varios patrones de diseño, como el patrón Estrategia, donde se puede cambiar dinámicamente el comportamiento de un método en tiempo de ejecución al pasar diferentes implementaciones de delegados.

Nota:

El escenario de control de eventos se trata en un módulo independiente junto con una introducción al uso de eventos en aplicaciones de C#.

Puntos clave

  • Las instancias de delegado se pueden crear mediante métodos con nombre, conversión de grupos de métodos, métodos anónimos o expresiones lambda.
  • Los delegados se pueden invocar como métodos normales y se pueden combinar para crear delegados de multidifusión.
  • Los delegados se utilizan en diversos escenarios, como la ordenación y el filtrado, los métodos de llamada de retorno, la programación asincrónica, la gestión de eventos y la implementación de patrones de diseño.