CSharp

Tutorial CSharp: Delegados

Aprende los fundamentos de delegados en C#, incluyendo sintaxis, Action, Func, Predicate y delegados multicast para programación avanzada.

Aprende CSharp y certifícate

Definición y sintaxis

Los delegados en C# son tipos de referencia que representan métodos con una firma específica. Funcionan como punteros a métodos, permitiendo pasar métodos como parámetros, almacenarlos como variables o devolverlos como valores de retorno. Esta característica es fundamental para implementar callbacks, eventos y programación asíncrona.

Un delegado define un tipo que especifica una firma de método particular, incluyendo el tipo de retorno y los parámetros. Cualquier método que coincida con esa firma puede ser asignado a una variable de ese tipo delegado.

Declaración de un delegado

La sintaxis para declarar un delegado es la siguiente:

[modificadores] delegate TipoRetorno NombreDelegado([parámetros]);

Donde:

  • modificadores: pueden ser public, internal, private, etc.
  • TipoRetorno: es el tipo de dato que devolverá el método referenciado
  • NombreDelegado: es el nombre del tipo delegado (por convención suelen terminar en "Delegate" o "Handler")
  • parámetros: lista opcional de parámetros que debe tener el método referenciado

Veamos un ejemplo sencillo:

// Declaración de un delegado que acepta un string y devuelve un int
public delegate int ProcesadorTextoDelegate(string texto);

Este delegado puede referenciar cualquier método que acepte un string como parámetro y devuelva un int.

Uso básico de delegados

Para utilizar un delegado, primero debemos crear una instancia y asignarle un método compatible:

using System;

class Program
{
    // Declaración del delegado
    public delegate void MensajeDelegate(string mensaje);
    
    static void Main()
    {
        // Creación de una instancia del delegado que apunta al método MostrarMensaje
        MensajeDelegate delegado = MostrarMensaje;
        
        // Invocación del delegado
        delegado("Hola desde un delegado");
        
        // Asignación de otro método al mismo delegado
        delegado = MostrarMensajeEnMayusculas;
        
        // Invocación del delegado con el nuevo método
        delegado("Hola desde un delegado");
    }
    
    static void MostrarMensaje(string mensaje)
    {
        Console.WriteLine($"Mensaje: {mensaje}");
    }
    
    static void MostrarMensajeEnMayusculas(string mensaje)
    {
        Console.WriteLine($"Mensaje: {mensaje.ToUpper()}");
    }
}

En este ejemplo, creamos un delegado llamado MensajeDelegate que puede referenciar cualquier método que acepte un string y no devuelva nada (void). Luego, creamos una instancia del delegado y le asignamos el método MostrarMensaje. Cuando invocamos el delegado, se ejecuta el método referenciado.

Métodos anónimos con delegados

También podemos asignar métodos anónimos a los delegados, sin necesidad de definir un método con nombre:

using System;

class Program
{
    public delegate int CalculadoraDelegate(int a, int b);
    
    static void Main()
    {
        // Usando un método anónimo
        CalculadoraDelegate suma = delegate(int x, int y) {
            return x + y;
        };
        
        int resultado = suma(5, 3);
        Console.WriteLine($"Resultado: {resultado}");  // Muestra: Resultado: 8
    }
}

Delegados como parámetros

Una de las aplicaciones más útiles de los delegados es pasarlos como parámetros a otros métodos:

using System;

class Program
{
    public delegate bool FiltradorDelegate(int numero);
    
    static void Main()
    {
        int[] numeros = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        
        // Filtrar números pares
        MostrarNumerosFiltrados(numeros, EsPar);
        
        // Filtrar números mayores que 5
        MostrarNumerosFiltrados(numeros, n => n > 5);
    }
    
    static void MostrarNumerosFiltrados(int[] numeros, FiltradorDelegate filtro)
    {
        Console.WriteLine("Números filtrados:");
        foreach (int n in numeros)
        {
            if (filtro(n))
            {
                Console.Write($"{n} ");
            }
        }
        Console.WriteLine();
    }
    
    static bool EsPar(int numero)
    {
        return numero % 2 == 0;
    }
}

En este ejemplo, el método MostrarNumerosFiltrados acepta un delegado como parámetro, lo que permite cambiar el comportamiento del filtrado sin modificar el método.

Expresiones lambda con delegados

Las expresiones lambda proporcionan una sintaxis más concisa para crear delegados:

using System;

class Program
{
    public delegate int OperacionDelegate(int x, int y);
    
    static void Main()
    {
        // Usando expresión lambda
        OperacionDelegate multiplicar = (x, y) => x * y;
        
        int resultado = multiplicar(4, 5);
        Console.WriteLine($"4 x 5 = {resultado}");  // Muestra: 4 x 5 = 20
    }
}

La expresión lambda (x, y) => x * y es equivalente a definir un método que multiplica dos números, pero con una sintaxis más compacta.

Compatibilidad de covarianza y contravarianza

Los delegados en C# soportan covarianza para tipos de retorno y contravarianza para parámetros:

using System;

class Animal { }
class Perro : Animal { }

class Program
{
    delegate Animal CreadorAnimalDelegate();
    delegate void ManejadorAnimalDelegate(Animal animal);
    
    static void Main()
    {
        // Covarianza: un método que devuelve Perro puede asignarse a un delegado que devuelve Animal
        CreadorAnimalDelegate creador = CrearPerro;
        
        // Contravarianza: un método que acepta Animal puede asignarse a un delegado que acepta Perro
        ManejadorAnimalDelegate manejador = ManejarAnimal;
    }
    
    static Perro CrearPerro()
    {
        return new Perro();
    }
    
    static void ManejarAnimal(Animal animal)
    {
        Console.WriteLine("Manejando un animal");
    }
}

Los delegados son un concepto fundamental en C# que permite implementar patrones de diseño avanzados y facilita la programación orientada a eventos. En las siguientes secciones, exploraremos los delegados predefinidos (Action, Func, Predicate) y los delegados multicast.

Action, Func, Predicate

C# proporciona varios delegados genéricos predefinidos que simplifican el trabajo con métodos como parámetros. Estos delegados integrados en el framework eliminan la necesidad de definir delegados personalizados para casos de uso comunes, haciendo el código más limpio y estandarizado.

Delegado Action

El delegado Action representa un método que no devuelve un valor (void) y puede aceptar de 0 a 16 parámetros. Es ideal para operaciones que realizan una acción sin necesidad de retornar información.

La familia de delegados Action incluye:

// Sin parámetros
Action miAccion = () => Console.WriteLine("Acción ejecutada");

// Con un parámetro
Action<string> mostrarMensaje = mensaje => Console.WriteLine(mensaje);

// Con múltiples parámetros
Action<string, int> repetirMensaje = (mensaje, veces) => {
    for (int i = 0; i < veces; i++)
        Console.WriteLine(mensaje);
};

Veamos un ejemplo práctico:

using System;

class Program
{
    static void Main()
    {
        // Crear instancias de Action
        Action saludar = () => Console.WriteLine("¡Hola mundo!");
        Action<string> saludarPersona = nombre => Console.WriteLine($"¡Hola {nombre}!");
        Action<string, string> saludarCompleto = (nombre, apellido) => 
            Console.WriteLine($"¡Hola {nombre} {apellido}!");
        
        // Invocar los delegados
        saludar();                     // Muestra: ¡Hola mundo!
        saludarPersona("Ana");         // Muestra: ¡Hola Ana!
        saludarCompleto("Juan", "Pérez"); // Muestra: ¡Hola Juan Pérez!
        
        // Usar Action como parámetro
        ProcesarDatos("Datos importantes", MostrarInformacion);
        ProcesarDatos("Datos críticos", datos => Console.WriteLine($"URGENTE: {datos}"));
    }
    
    static void MostrarInformacion(string info)
    {
        Console.WriteLine($"INFO: {info}");
    }
    
    static void ProcesarDatos(string datos, Action<string> procesador)
    {
        // Realizar algún procesamiento...
        Console.WriteLine("Procesando datos...");
        
        // Llamar al delegado
        procesador(datos);
    }
}

Delegado Func

El delegado Func representa un método que devuelve un valor y puede aceptar de 0 a 16 parámetros. El último parámetro de tipo en la definición genérica siempre representa el tipo de retorno.

// Sin parámetros, devuelve string
Func<string> obtenerSaludo = () => "¡Hola mundo!";

// Un parámetro int, devuelve bool
Func<int, bool> esPar = numero => numero % 2 == 0;

// Dos parámetros int, devuelve int
Func<int, int, int> sumar = (a, b) => a + b;

Ejemplo de uso de Func en un contexto más elaborado:

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        // Crear instancias de Func
        Func<DateTime> obtenerFechaActual = () => DateTime.Now;
        Func<int, int, int> calcularPotencia = (baseNum, exponente) => {
            return (int)Math.Pow(baseNum, exponente);
        };
        
        // Invocar los delegados
        Console.WriteLine($"Fecha actual: {obtenerFechaActual()}");
        Console.WriteLine($"2^3 = {calcularPotencia(2, 3)}");  // Muestra: 2^3 = 8
        
        // Usar Func para transformar datos
        List<int> numeros = new List<int> { 1, 2, 3, 4, 5 };
        List<int> cuadrados = TransformarLista(numeros, n => n * n);
        
        Console.WriteLine("Cuadrados:");
        foreach (int num in cuadrados)
        {
            Console.Write($"{num} ");  // Muestra: 1 4 9 16 25
        }
    }
    
    static List<T2> TransformarLista<T1, T2>(List<T1> lista, Func<T1, T2> transformador)
    {
        List<T2> resultado = new List<T2>();
        foreach (T1 item in lista)
        {
            resultado.Add(transformador(item));
        }
        return resultado;
    }
}

Delegado Predicate

El delegado Predicate es un caso especial que representa un método que recibe un parámetro y devuelve un valor booleano. Es equivalente a Func<T, bool> y se utiliza principalmente para operaciones de filtrado.

// Predicate<T> siempre devuelve bool
Predicate<int> esMayorDeEdad = edad => edad >= 18;
Predicate<string> esCorreoValido = correo => correo.Contains("@") && correo.Contains(".");

Ejemplo práctico con Predicate:

using System;
using System.Collections.Generic;

class Producto
{
    public string Nombre { get; set; }
    public decimal Precio { get; set; }
    public string Categoria { get; set; }
}

class Program
{
    static void Main()
    {
        List<Producto> productos = new List<Producto>
        {
            new Producto { Nombre = "Laptop", Precio = 1200, Categoria = "Electrónica" },
            new Producto { Nombre = "Teléfono", Precio = 800, Categoria = "Electrónica" },
            new Producto { Nombre = "Mesa", Precio = 300, Categoria = "Muebles" },
            new Producto { Nombre = "Silla", Precio = 150, Categoria = "Muebles" }
        };
        
        // Filtrar productos caros (más de 500)
        Predicate<Producto> esProductoCaro = p => p.Precio > 500;
        List<Producto> productosCostosos = productos.FindAll(esProductoCaro);
        
        Console.WriteLine("Productos costosos:");
        foreach (var producto in productosCostosos)
        {
            Console.WriteLine($"- {producto.Nombre}: {producto.Precio:C}");
        }
        
        // Filtrar por categoría usando método separado
        List<Producto> electronicos = FiltrarPorCategoria(productos, "Electrónica");
        
        Console.WriteLine("\nProductos electrónicos:");
        foreach (var producto in electronicos)
        {
            Console.WriteLine($"- {producto.Nombre}");
        }
    }
    
    static List<T> FiltrarPorCategoria<T>(List<T> items, string categoria) where T : Producto
    {
        // Usando Predicate como parámetro implícito
        return items.FindAll(item => item.Categoria == categoria);
    }
}

Comparación y elección entre Action, Func y Predicate

La elección entre estos delegados predefinidos depende del propósito específico:

  • Action: Cuando necesites ejecutar un método que no devuelve valor (void).
  • Func: Cuando necesites un método que devuelva un valor de cualquier tipo.
  • Predicate: Cuando necesites un método que evalúe una condición y devuelva true/false.

Ejemplo comparativo:

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> numeros = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        
        // Action - Realizar una operación sin devolver valor
        Action<int> mostrar = n => Console.Write($"{n} ");
        Console.Write("Todos los números: ");
        numeros.ForEach(mostrar);
        
        Console.WriteLine();
        
        // Func - Transformar valores
        Func<int, string> formatear = n => $"Número: {n}";
        List<string> textos = numeros.ConvertAll(n => formatear(n));
        Console.WriteLine($"Primer texto formateado: {textos[0]}");
        
        // Predicate - Filtrar valores
        Predicate<int> esDivisiblePorTres = n => n % 3 == 0;
        List<int> divisiblesPorTres = numeros.FindAll(esDivisiblePorTres);
        
        Console.Write("Divisibles por tres: ");
        divisiblesPorTres.ForEach(mostrar);
    }
}

Estos delegados predefinidos son ampliamente utilizados en la programación moderna con C#, especialmente en:

  • LINQ: Las consultas LINQ utilizan Func y Predicate internamente.
  • Programación asíncrona: Los métodos Task utilizan Action y Func.
  • Eventos y callbacks: Action se usa frecuentemente para manejar eventos.
  • Algoritmos de colecciones: Los métodos de List como ForEach, Find, etc.

La comprensión y uso adecuado de estos delegados predefinidos es fundamental para escribir código C# moderno, conciso y mantenible.

Delegados multicast

Los delegados multicast son una característica poderosa de C# que permite que un solo delegado apunte a múltiples métodos. Cuando se invoca un delegado multicast, todos los métodos referenciados se ejecutan secuencialmente en el orden en que fueron agregados. Esta funcionalidad es especialmente útil para implementar sistemas de notificación, donde múltiples componentes necesitan responder a un mismo evento.

En C#, todos los delegados son inherentemente multicast gracias a que derivan de la clase base MulticastDelegate, que a su vez hereda de Delegate. Esto significa que cualquier delegado que definamos puede comportarse como un delegado multicast.

Operaciones con delegados multicast

Para crear un delegado multicast, utilizamos los operadores += y -= para agregar o quitar métodos:

using System;

class Program
{
    // Definición del delegado
    public delegate void Notificador(string mensaje);
    
    static void Main()
    {
        // Creamos un delegado vacío
        Notificador notificacion = null;
        
        // Agregamos métodos al delegado
        notificacion += EnviarEmail;
        notificacion += EnviarSMS;
        notificacion += MostrarEnConsola;
        
        // Invocamos el delegado multicast
        Console.WriteLine("Enviando notificación a todos los canales:");
        notificacion?.Invoke("Sistema iniciado correctamente");
        
        Console.WriteLine("\nQuitando notificación por SMS:");
        // Quitamos un método del delegado
        notificacion -= EnviarSMS;
        
        // Invocamos nuevamente
        notificacion?.Invoke("Actualización completada");
    }
    
    static void EnviarEmail(string mensaje)
    {
        Console.WriteLine($"EMAIL: {mensaje}");
    }
    
    static void EnviarSMS(string mensaje)
    {
        Console.WriteLine($"SMS: {mensaje}");
    }
    
    static void MostrarEnConsola(string mensaje)
    {
        Console.WriteLine($"CONSOLA: {mensaje}");
    }
}

En este ejemplo, creamos un delegado multicast notificacion que apunta a tres métodos diferentes. Al invocar el delegado, los tres métodos se ejecutan en secuencia. Luego, quitamos uno de los métodos y al invocar nuevamente, solo se ejecutan los dos restantes.

Consideraciones sobre el valor de retorno

Un aspecto importante a tener en cuenta es que los delegados multicast solo pueden devolver valores de manera efectiva cuando el tipo de retorno es void. Si el delegado tiene un tipo de retorno no void, solo se devolverá el valor del último método ejecutado:

using System;

class Program
{
    public delegate int Calculador(int x, int y);
    
    static void Main()
    {
        // Creamos un delegado multicast con tipo de retorno no void
        Calculador operaciones = Sumar;
        operaciones += Restar;
        operaciones += Multiplicar;
        
        // Al invocar, solo obtenemos el resultado del último método (Multiplicar)
        int resultado = operaciones(10, 5);
        Console.WriteLine($"Resultado: {resultado}");  // Muestra: Resultado: 50
    }
    
    static int Sumar(int a, int b)
    {
        int resultado = a + b;
        Console.WriteLine($"Suma: {resultado}");
        return resultado;
    }
    
    static int Restar(int a, int b)
    {
        int resultado = a - b;
        Console.WriteLine($"Resta: {resultado}");
        return resultado;
    }
    
    static int Multiplicar(int a, int b)
    {
        int resultado = a * b;
        Console.WriteLine($"Multiplicación: {resultado}");
        return resultado;
    }
}

En este ejemplo, aunque los tres métodos se ejecutan y muestran sus resultados por consola, la variable resultado solo contiene el valor devuelto por el último método ejecutado (Multiplicar).

Obtención de todos los resultados

Si necesitamos obtener los resultados de todos los métodos en un delegado multicast, podemos usar la reflexión para obtener la lista de delegados y ejecutarlos individualmente:

using System;
using System.Collections.Generic;

class Program
{
    public delegate int Transformador(int valor);
    
    static void Main()
    {
        // Creamos un delegado multicast
        Transformador transformaciones = Duplicar;
        transformaciones += Cuadrado;
        transformaciones += Incrementar;
        
        int numero = 5;
        Console.WriteLine($"Número original: {numero}");
        
        // Obtenemos todos los resultados
        List<int> resultados = ObtenerTodosLosResultados(transformaciones, numero);
        
        Console.WriteLine("Resultados de todas las transformaciones:");
        foreach (int resultado in resultados)
        {
            Console.WriteLine($"- {resultado}");
        }
    }
    
    static List<T> ObtenerTodosLosResultados<T>(Delegate delegadoMulticast, params object[] args)
    {
        List<T> resultados = new List<T>();
        
        // Si el delegado no es nulo
        if (delegadoMulticast != null)
        {
            // Obtenemos la lista de delegados individuales
            foreach (Delegate delegado in delegadoMulticast.GetInvocationList())
            {
                // Invocamos cada delegado y guardamos su resultado
                T resultado = (T)delegado.DynamicInvoke(args);
                resultados.Add(resultado);
            }
        }
        
        return resultados;
    }
    
    static int Duplicar(int n)
    {
        return n * 2;
    }
    
    static int Cuadrado(int n)
    {
        return n * n;
    }
    
    static int Incrementar(int n)
    {
        return n + 1;
    }
}

Este código muestra cómo podemos obtener los resultados de todos los métodos en un delegado multicast utilizando el método GetInvocationList(), que devuelve un array con todos los delegados individuales.

Manejo de excepciones en delegados multicast

Cuando trabajamos con delegados multicast, es importante considerar cómo manejar las excepciones. Si uno de los métodos en la cadena lanza una excepción, los métodos subsiguientes no se ejecutarán:

using System;

class Program
{
    public delegate void Procesador();
    
    static void Main()
    {
        Procesador proceso = PrimerPaso;
        proceso += SegundoPaso;
        proceso += TercerPaso;
        
        try
        {
            proceso();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
            Console.WriteLine("El proceso se interrumpió.");
        }
    }
    
    static void PrimerPaso()
    {
        Console.WriteLine("Primer paso completado");
    }
    
    static void SegundoPaso()
    {
        Console.WriteLine("Iniciando segundo paso...");
        throw new InvalidOperationException("Error en el segundo paso");
    }
    
    static void TercerPaso()
    {
        Console.WriteLine("Tercer paso completado");
    }
}

En este ejemplo, cuando SegundoPaso lanza una excepción, TercerPaso nunca se ejecuta. Si necesitamos que todos los métodos se ejecuten independientemente de las excepciones, debemos implementar un manejo de excepciones más robusto:

using System;

class Program
{
    public delegate void Procesador();
    
    static void Main()
    {
        Procesador proceso = PrimerPaso;
        proceso += SegundoPaso;
        proceso += TercerPaso;
        
        // Ejecutamos cada delegado individualmente con manejo de excepciones
        foreach (Procesador paso in proceso.GetInvocationList())
        {
            try
            {
                paso();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error en un paso: {ex.Message}");
                Console.WriteLine("Continuando con el siguiente paso...");
            }
        }
        
        Console.WriteLine("Proceso completo");
    }
    
    static void PrimerPaso()
    {
        Console.WriteLine("Primer paso completado");
    }
    
    static void SegundoPaso()
    {
        Console.WriteLine("Iniciando segundo paso...");
        throw new InvalidOperationException("Error en el segundo paso");
    }
    
    static void TercerPaso()
    {
        Console.WriteLine("Tercer paso completado");
    }
}

Aplicaciones prácticas de delegados multicast

Los delegados multicast son especialmente útiles en escenarios como:

  • Sistemas de notificación: Cuando múltiples componentes necesitan ser notificados de un cambio.
  • Validación de datos: Ejecutar múltiples validaciones sobre un conjunto de datos.
  • Procesamiento en cadena: Aplicar una serie de transformaciones a un dato.

Veamos un ejemplo de un sistema de validación simple:

using System;
using System.Collections.Generic;

class Producto
{
    public string Nombre { get; set; }
    public decimal Precio { get; set; }
    public int Stock { get; set; }
}

class Program
{
    // Delegado para validación que devuelve un mensaje de error o null si es válido
    public delegate string Validador(Producto producto);
    
    static void Main()
    {
        // Creamos un producto para validar
        Producto producto = new Producto
        {
            Nombre = "",
            Precio = -50,
            Stock = 10
        };
        
        // Configuramos las validaciones
        Validador validaciones = ValidarNombre;
        validaciones += ValidarPrecio;
        validaciones += ValidarStock;
        
        // Validamos el producto
        bool esValido = true;
        List<string> errores = new List<string>();
        
        foreach (Validador validador in validaciones.GetInvocationList())
        {
            string error = validador(producto);
            if (error != null)
            {
                esValido = false;
                errores.Add(error);
            }
        }
        
        // Mostramos el resultado
        if (esValido)
        {
            Console.WriteLine("El producto es válido");
        }
        else
        {
            Console.WriteLine("El producto tiene los siguientes errores:");
            foreach (string error in errores)
            {
                Console.WriteLine($"- {error}");
            }
        }
    }
    
    static string ValidarNombre(Producto p)
    {
        if (string.IsNullOrWhiteSpace(p.Nombre))
            return "El nombre no puede estar vacío";
        return null;
    }
    
    static string ValidarPrecio(Producto p)
    {
        if (p.Precio <= 0)
            return "El precio debe ser mayor que cero";
        return null;
    }
    
    static string ValidarStock(Producto p)
    {
        if (p.Stock < 0)
            return "El stock no puede ser negativo";
        return null;
    }
}

Este ejemplo muestra cómo podemos usar delegados multicast para implementar un sistema de validación flexible, donde cada validación es independiente y podemos agregar o quitar validaciones según sea necesario.

Los delegados multicast son una herramienta fundamental en C# que permite implementar patrones de diseño como Observer, Chain of Responsibility y Command de manera elegante y flexible. Su capacidad para manejar múltiples suscriptores los hace ideales para sistemas basados en eventos, donde la comunicación desacoplada entre componentes es esencial.

CONSTRUYE TU CARRERA EN IA Y PROGRAMACIÓN SOFTWARE

Accede a +1000 lecciones y cursos con certificado. Mejora tu portfolio con certificados de superación para tu CV.

30 % DE DESCUENTO

Plan mensual

19.00 /mes

13.30 € /mes

Precio normal mensual: 19 €
63 % DE DESCUENTO

Plan anual

10.00 /mes

7.00 € /mes

Ahorras 144 € al año
Precio normal anual: 120 €
Aprende CSharp online

Ejercicios de esta lección Delegados

Evalúa tus conocimientos de esta lección Delegados con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de CSharp

Accede a todas las lecciones de CSharp y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A C#

Introducción Y Entorno

Creación De Proyecto C#

Introducción Y Entorno

Variables Y Constantes

Sintaxis

Tipos De Datos

Sintaxis

Operadores

Sintaxis

Control De Flujo

Sintaxis

Funciones

Sintaxis

Estructuras De Control Iterativo

Sintaxis

Interpolación De Strings

Sintaxis

Estructuras De Control Condicional

Sintaxis

Manejo De Valores Nulos

Sintaxis

Clases Y Encapsulación

Programación Orientada A Objetos

Objetos

Programación Orientada A Objetos

Constructores Y Destructores

Programación Orientada A Objetos

Herencia

Programación Orientada A Objetos

Polimorfismo

Programación Orientada A Objetos

Genéricos

Programación Orientada A Objetos

Métodos Virtuales Y Sobrecarga

Programación Orientada A Objetos

Clases Abstractas

Programación Orientada A Objetos

Interfaces

Programación Orientada A Objetos

Propiedades Y Encapsulación

Programación Orientada A Objetos

Métodos De Extensión

Programación Orientada A Objetos

Clases Y Objetos

Programación Orientada A Objetos

Clases Parciales

Programación Orientada A Objetos

Miembros Estáticos

Programación Orientada A Objetos

Tuplas Y Tipos Anónimos

Programación Orientada A Objetos

Arrays Y Listas

Colecciones Y Linq

Diccionarios

Colecciones Y Linq

Conjuntos, Colas Y Pilas

Colecciones Y Linq

Uso De Consultas Linq

Colecciones Y Linq

Linq Avanzado

Colecciones Y Linq

Colas Y Pilas

Colecciones Y Linq

Conjuntos

Colecciones Y Linq

Linq Básico

Colecciones Y Linq

Delegados Funcionales

Programación Funcional

Records

Programación Funcional

Expresiones Lambda

Programación Funcional

Linq Funcional

Programación Funcional

Fundamentos De La Programación Funcional

Programación Funcional

Pattern Matching

Programación Funcional

Testing Unitario Con Xunit

Testing

Excepciones

Excepciones

Delegados

Programación Asíncrona

Eventos

Programación Asíncrona

Lambdas

Programación Asíncrona

Uso De Async Y Await

Programación Asíncrona

Tareas

Programación Asíncrona

Accede GRATIS a CSharp y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender qué son los delegados y cómo declararlos en C#.
  • Aprender a utilizar delegados con métodos nombrados, anónimos y expresiones lambda.
  • Conocer los delegados genéricos predefinidos Action, Func y Predicate y sus aplicaciones.
  • Entender el concepto y uso de delegados multicast para invocar múltiples métodos.
  • Saber manejar excepciones y obtener resultados en delegados multicast para escenarios avanzados.