Cargando...

Delegados y Eventos

Los delegados y eventos en C# son herramientas fundamentales para construir aplicaciones flexibles, modulares y desacopladas. Un delegado es un tipo que actúa como un puntero seguro a un método, permitiendo almacenar y llamar a métodos de manera dinámica en tiempo de ejecución. Los eventos se basan en delegados y permiten implementar el patrón publicador-suscriptor (Publisher-Subscriber), de manera que los objetos puedan reaccionar ante acciones de otros objetos sin acoplarse directamente a ellos.
En el desarrollo de software, los delegados y eventos se usan comúnmente en sistemas de notificaciones, interfaces de usuario, registro de logs, frameworks de extensibilidad y procesamiento asincrónico. Los delegados permiten invocar métodos sin conocer los detalles de implementación, mientras que los eventos permiten que múltiples suscriptores respondan a una acción compartida.
En este tutorial, aprenderás a definir, suscribirte y disparar eventos, a trabajar con delegados tipo seguro y a combinar estos conceptos con principios de programación orientada a objetos, estructuras de datos y algoritmos para resolver problemas reales en proyectos C#. También se mostrará cómo estos conceptos se integran dentro de la arquitectura del software para crear componentes desacoplados y mantenibles.

Ejemplo Básico

text
TEXT Code
using System;

namespace DelegatesAndEventsDemo
{
public delegate void NotificationHandler(string message);

public class Publisher
{
public event NotificationHandler Notify;

public void SendNotification(string message)
{
Notify?.Invoke(message);
}
}

public class Subscriber
{
private string _name;

public Subscriber(string name)
{
_name = name;
}

public void OnNotificationReceived(string message)
{
Console.WriteLine($"{_name} recibió el mensaje: {message}");
}
}

class Program
{
static void Main(string[] args)
{
Publisher publisher = new Publisher();

Subscriber alice = new Subscriber("Alicia");
Subscriber bob = new Subscriber("Bob");

publisher.Notify += alice.OnNotificationReceived;
publisher.Notify += bob.OnNotificationReceived;

publisher.SendNotification("¡Hola suscriptores!");

publisher.Notify -= bob.OnNotificationReceived;
publisher.SendNotification("Segundo mensaje");

Console.ReadLine();
}
}

En este ejemplo, el delegado NotificationHandler define la firma de los métodos que pueden asociarse al evento y garantiza seguridad de tipos. La clase Publisher contiene el evento Notify y lo invoca de forma segura usando ?.Invoke() para evitar errores si no hay suscriptores.
La clase Subscriber implementa el método OnNotificationReceived compatible con la firma del delegado. En Main, se crean instancias de Publisher y Subscriber, se suscriben y se cancelan suscripciones al evento, mostrando un patrón de observador y reduciendo acoplamientos. Esto previene problemas de memoria y facilita la mantenibilidad en aplicaciones reales.

Ejemplo Práctico

text
TEXT Code
using System;
using System.Collections.Generic;

namespace DelegatesAndEventsAdvanced
{
public delegate void DataProcessedHandler(int result);

public class DataProcessor
{
public event DataProcessedHandler DataProcessed;

public void ProcessData(List<int> data)
{
int sum = 0;
foreach (var num in data)
{
if (num < 0)
{
Console.WriteLine("Se ignoró valor negativo: " + num);
continue;
}
sum += num;
}

DataProcessed?.Invoke(sum);
}
}

public class Logger
{
public void LogResult(int result)
{
Console.WriteLine($"Resultado registrado: {result}");
}
}

public class Notifier
{
public void SendAlert(int result)
{
if (result > 50)
Console.WriteLine("¡Alerta! Resultado por encima del límite: " + result);
}
}

class Program
{
static void Main(string[] args)
{
DataProcessor processor = new DataProcessor();
Logger logger = new Logger();
Notifier notifier = new Notifier();

processor.DataProcessed += logger.LogResult;
processor.DataProcessed += notifier.SendAlert;

List<int> sampleData = new List<int> { 10, 20, 30, -5 };
processor.ProcessData(sampleData);

Console.ReadLine();
}
}

En este ejemplo, DataProcessor ignora valores negativos y suma los positivos. El evento DataProcessed permite a Logger y Notifier reaccionar al resultado sin conocer detalles del procesamiento. Logger registra el resultado y Notifier genera alertas si se excede un umbral. Este ejemplo ilustra el patrón Observer, el principio de responsabilidad única (SRP), invocación segura de eventos, bajo acoplamiento y buenas prácticas en manejo de errores.

Mejores prácticas y errores comunes en C#:

  • Usar delegados y eventos tipo seguro y encapsulados.
  • Invocar eventos con ?.Invoke() para evitar NullReferenceException.
  • Desuscribirse de eventos cuando ya no se necesiten para prevenir memory leaks.
  • Evitar delegados anónimos de larga duración.
  • No realizar operaciones largas en el hilo principal dentro de eventos frecuentes.
  • Minimizar la asignación de objetos en eventos de alta frecuencia.
  • Validar datos antes de disparar eventos.

📊 Tabla de Referencia

C# Element/Concept Description Usage Example
Delegate Tipo seguro que apunta a un método public delegate void MyDelegate(int x);
Event Evento basado en delegado public event MyDelegate MyEvent;
Subscription Suscripción a un evento myPublisher.MyEvent += mySubscriber.MyMethod;
Unsubscription Cancelar suscripción myPublisher.MyEvent -= mySubscriber.MyMethod;
Conditional Invocation Invocación segura de evento MyEvent?.Invoke(42);
Anonymous Delegate Delegado definido inline myPublisher.MyEvent += (x) => Console.WriteLine(x);

Resumen y próximos pasos:
Los delegados y eventos proporcionan una arquitectura flexible y desacoplada en aplicaciones C#. Conceptos clave incluyen delegados tipo seguro, definición de eventos, suscripción segura y el patrón Observer.
Para avanzar, se recomienda estudiar programación asincrónica, combinar delegados con LINQ y arquitecturas basadas en eventos. Aplicaciones prácticas incluyen sistemas de notificación, frameworks extensibles y procesamiento de datos en tiempo real. Recursos adicionales incluyen documentación oficial de Microsoft y proyectos open-source.

🧠 Pon a Prueba tu Conocimiento

Listo para Empezar

Test Your Knowledge

Test your understanding of this topic with practical questions.

4
Preguntas
🎯
70%
Para Aprobar
♾️
Tiempo
🔄
Intentos

📝 Instrucciones

  • Lee cada pregunta cuidadosamente
  • Selecciona la mejor respuesta para cada pregunta
  • Puedes repetir el quiz tantas veces como quieras
  • Tu progreso se mostrará en la parte superior