Da trilha de C# Este conceito ainda não saiu como card do dia. ir para o card de hoje

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

  • delegate define um tipo que descreve a assinatura de métodos que podem ser referenciados.
  • Func<T> e Action<T> são delegates genéricos internos para evitar declarações personalizadas.
  • event restringe 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 contra null.
delegates_eventos.cs
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)}");
    }
}

Exercícios

  1. 1
    Fácil

    Delegate personalizado para operações matemáticas

    Crie um delegate chamado Calculadora que recebe dois inteiros e retorna um inteiro. No método Main, atribua a esse delegate uma expressão lambda que soma dois números e outra que multiplica. Exiba o resultado de cada operação.

    Resolver
  2. 2
    Médio

    Evento com múltiplos assinantes

    Crie uma classe Termometro que possui um evento TemperaturaMudou do tipo Action<double>. A classe deve ter um método AlterarTemperatura(double novaTemp) que dispara o evento. No Main, inscreva dois assinantes: um que imprime a temperatura em Celsius e outro que converte para Fahrenheit. Altere a temperatura e exiba as mensagens.

    Resolver
  3. 3
    Desafio

    Sistema de pedidos com eventos e cancelamento de inscrição

    Implemente um sistema de pedidos onde a classe Pedido possui um evento PedidoCriado do tipo EventHandler<PedidoEventArgs>. Crie a classe PedidoEventArgs com uma propriedade Id e Valor. No Main, inscreva três assinantes: um para log, um para enviar e-mail e um para atualizar estoque. Após criar um pedido, cancele a inscrição do assinante de e-mail e crie outro pedido. Exiba as mensagens na ordem correta.

    Resolver

Continue estudando