C# Funções Intermediário
Delegates e eventos
Em C#, um delegate é um tipo que representa referências a métodos com uma assinatura específica. Ele permite tratar métodos como valores, armazenando-os em variáveis e passando-os como parâmetros. Isso é a base para callbacks e programação orientada a eventos.
A biblioteca padrão já traz delegates genéricos prontos: Func<...> para métodos que retornam valor e Action<...> para métodos que não retornam. Usar esses tipos evita declarar delegates personalizados na maioria dos casos.
Um evento é um membro de classe que encapsula um delegate, permitindo que apenas a classe declare e dispare o evento, enquanto outras classes podem apenas se inscrever (+=) ou cancelar a inscrição (-=). Isso implementa o padrão publisher/subscriber com segurança.
Delegates podem ser multicast: podem referenciar vários métodos. Quando invocados, todos são chamados em ordem. Eventos usam essa característica para notificar múltiplos assinantes.
Pontos-chave
delegatedefine um tipo que descreve a assinatura de métodos que podem ser referenciados.Func<T>eAction<T>são delegates genéricos internos para evitar declarações personalizadas.eventrestringe o acesso ao delegate: só a classe declara e dispara; fora dela, apenas+=e-=.- Delegates multicast (
+=) invocam todos os métodos inscritos na ordem de inscrição. - Use
?.Invoke()para disparar eventos com segurança contranull.
using System;
// Declaração de um delegate personalizado
public delegate void Notificador(string mensagem);
public class Publicador
{
// Evento baseado no delegate Notificador
public event Notificador? AoPublicar;
public void Publicar(string texto)
{
Console.WriteLine($"Publicando: {texto}");
// Dispara o evento de forma segura (null-conditional)
AoPublicar?.Invoke(texto);
}
}
public class Programa
{
public static void Main()
{
var pub = new Publicador();
// Inscreve dois assinantes (multicast)
pub.AoPublicar += msg => Console.WriteLine($"Assinante 1 recebeu: {msg}");
pub.AoPublicar += msg => Console.WriteLine($"Assinante 2 recebeu: {msg}");
pub.Publicar("Olá, eventos!");
// Cancela a inscrição do primeiro assinante
// (precisamos de uma referência nomeada para remover)
Notificador assinante1 = msg => Console.WriteLine($"Assinante 1 recebeu: {msg}");
pub.AoPublicar -= assinante1; // não remove o lambda anterior, pois são instâncias diferentes
// Usando Action para simplificar
Action<string> acao = msg => Console.WriteLine($"Action: {msg}");
acao("Teste com Action");
// Usando Func para retornar valor
Func<int, int, int> soma = (a, b) => a + b;
Console.WriteLine($"Soma: {soma(3, 4)}");
}
}