Carregando...

Delegates e Eventos

Delegates e Eventos são recursos fundamentais em C# que permitem construir aplicações altamente flexíveis, modulares e de baixo acoplamento. Um delegate é um tipo seguro de ponteiro para método, que possibilita armazenar referências a métodos e invocá-los dinamicamente em tempo de execução. Eventos, por sua vez, são construídos com base em delegates e implementam o padrão "publisher-subscriber", permitindo que objetos notifiquem outros objetos sobre ações específicas sem criar dependências fortes.
O uso de delegates e eventos é comum em sistemas de notificação, interfaces gráficas, logging, frameworks de plugins e processamento assíncrono. Delegates permitem chamar métodos sem conhecimento prévio da implementação concreta, enquanto eventos possibilitam múltiplos assinantes reagirem a uma mesma ação do publisher.
Neste tutorial, você aprenderá a criar, assinar e invocar delegates, definir eventos e gerenciar assinaturas, integrando estes conceitos com princípios de OOP, estruturas de dados e algoritmos para resolver problemas práticos em C#. Além disso, exploraremos como esses mecanismos se encaixam na arquitetura de sistemas, garantindo componentes desacoplados e manutenção facilitada.

Exemplo 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} recebeu a mensagem: {message}");
}
}

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

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

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

publisher.SendNotification("Olá, assinantes!");

publisher.Notify -= bob.OnNotificationReceived;
publisher.SendNotification("Segunda notificação");

Console.ReadLine();
}
}

No exemplo acima, o delegate NotificationHandler define a assinatura dos métodos que podem ser associados ao evento, garantindo segurança de tipo. A classe Publisher contém o evento Notify, que é invocado de forma segura usando o operador ?.Invoke(), prevenindo exceções caso não haja assinantes.
A classe Subscriber implementa o método OnNotificationReceived, compatível com a assinatura do delegate. No método Main, criamos objetos Publisher e Subscriber, demonstrando assinatura e remoção de eventos, controlando o ciclo de vida dos assinantes. Este padrão implementa desacoplamento, chamadas seguras e prevenção de memory leaks, essenciais em aplicações complexas de C#.

Exemplo Prático

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("Valor negativo ignorado: " + 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 acima do limite: " + 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();
}
}

Neste exemplo, DataProcessor soma apenas os valores positivos da lista, ignorando valores negativos com mensagem de log. O evento DataProcessed permite que classes Logger e Notifier reajam ao resultado sem conhecer os detalhes do processamento. Logger registra o resultado, enquanto Notifier envia alerta caso ultrapasse um limite.
Este exemplo demonstra o padrão Observer, o princípio de responsabilidade única (SRP), chamadas seguras de eventos, baixo acoplamento e boas práticas de tratamento de exceções.

Boas práticas e erros comuns em C#:

  • Sempre usar delegates tipados e eventos encapsulados.
  • Invocar eventos com ?.Invoke() para evitar NullReferenceException.
  • Remover assinantes que não são mais necessários para prevenir memory leaks.
  • Evitar o uso de delegates anônimos para assinaturas de longa duração.
  • Não realizar operações longas no thread principal em eventos frequentes.
  • Minimizar alocações de objetos em eventos de alta frequência.
  • Validar dados antes de invocar eventos.

📊 Tabela de Referência

C# Element/Concept Description Usage Example
Delegate Tipo seguro de ponteiro para método public delegate void MyDelegate(int x);
Event Evento baseado em delegate public event MyDelegate MyEvent;
Subscription Assinatura de evento myPublisher.MyEvent += mySubscriber.MyMethod;
Unsubscription Remoção de assinatura myPublisher.MyEvent -= mySubscriber.MyMethod;
Conditional Invocation Chamada segura de evento MyEvent?.Invoke(42);
Anonymous Delegate Delegate definido inline myPublisher.MyEvent += (x) => Console.WriteLine(x);

Resumo e próximos passos:
Delegates e Eventos fornecem arquitetura flexível e desacoplada em aplicações C#. Conceitos-chave incluem delegates tipados, definição de eventos, assinaturas seguras e aplicação do padrão Observer.
Para avançar, recomenda-se estudar programação assíncrona, integração de delegates com LINQ e arquiteturas baseadas em eventos. Aplicações práticas incluem sistemas de notificação, frameworks de plugins e processamento de dados em tempo real. Recursos adicionais podem ser encontrados na documentação oficial da Microsoft e em projetos open-source.

🧠 Teste Seu Conhecimento

Pronto para Começar

Test Your Knowledge

Test your understanding of this topic with practical questions.

4
Perguntas
🎯
70%
Para Passar
♾️
Tempo
🔄
Tentativas

📝 Instruções

  • Leia cada pergunta cuidadosamente
  • Selecione a melhor resposta para cada pergunta
  • Você pode refazer o quiz quantas vezes quiser
  • Seu progresso será mostrado no topo