💻 Exemplos: Capítulo 13: Delegates, Eventos Fortemente Tipados e Lambdas

Especialização em Sistemas com C# • Demonstrações Práticas Compiláveis


🎯 Objetivo dos Exemplos

Apresentar a programação orientada a eventos e desacoplamento de componentes no .NET: delegates pré-definidos (Action, Func, Predicate), implementação do padrão Publisher/Subscriber com event EventHandler<TEventArgs> fortemente tipado e prevenção de vazamento de memória por assinaturas não canceladas (Event Memory Leaks).


1. Código Fonte Completo (Program.cs)

/**
 * @file Program.cs
 * @brief Delegates, eventos desacoplados e padrão publisher/subscriber em C# 12.
 */

using System;

Console.WriteLine("=== CAPÍTULO 13: DELEGATES, EVENTOS E PROGRAMAÇÃO REATIVA ===");

// 1. Definição do Evento com Dados Tipados (EventArgs)
public class TelemetriaEventArgs(string sensorId, double valor, bool emAlerta) : EventArgs
{
    public string SensorId { get; } = sensorId;
    public double Valor { get; } = valor;
    public bool EmAlerta { get; } = emAlerta;
    public DateTime Timestamp { get; } = DateTime.UtcNow;
}

// 2. Publisher (Emissor do Evento)
public class MonitorSensores
{
    // Evento padrão fortemente tipado
    public event EventHandler<TelemetriaEventArgs>? AmostraColetada;

    public void PublicarLeitura(string sensorId, double valor, double limiarAlerta)
    {
        bool alerta = valor >= limiarAlerta;
        var args = new TelemetriaEventArgs(sensorId, valor, alerta);

        Console.WriteLine($"[Publisher] Publicando leitura do sensor '{sensorId}': {valor:F2}");
        
        // Invocação thread-safe com operador de coalescência '?'
        AmostraColetada?.Invoke(this, args);
    }
}

// 3. Subscriber (Assinante do Evento)
public class PainelAlerta
{
    public void OnAmostraRecebida(object? sender, TelemetriaEventArgs e)
    {
        if (e.EmAlerta)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"  [PAINEL ALERTA] Sensor {e.SensorId} EXCEDEU LIMIAR! Valor: {e.Valor:F2} em {e.Timestamp:HH:mm:ss}");
            Console.ResetColor();
        }
        else
        {
            Console.WriteLine($"  [PAINEL STATUS] Sensor {e.SensorId} nominal ({e.Valor:F2}).");
        }
    }
}

// 4. Delegates Padronizados: Action, Func e Predicate
Action<string> logger = msg => Console.WriteLine($"[LOG ACTION] {msg}");
Func<double, double, double> multiplicador = (x, y) => x * y;
Predicate<int> isPar = num => num % 2 == 0;

logger("Delegates Action/Func inicializados.");
Console.WriteLine($"Func Multiplicador (4.5 * 2): {multiplicador(4.5, 2)}");
Console.WriteLine($"Predicate isPar(42): {isPar(42)}");

// Execução do Padrão Pub/Sub
Console.WriteLine("\n--- Conectando Assinantes ao Monitor de Sensores ---");
var monitor = new MonitorSensores();
var painel = new PainelAlerta();

// Inscrição (+ =)
monitor.AmostraColetada += painel.OnAmostraRecebida;

// Inscrição de handler anônimo via lambda
monitor.AmostraColetada += (sender, args) =>
{
    if (args.EmAlerta) Console.WriteLine("  [AUDITORIA] Registrando incidente em banco de dados.");
};

// Disparos de Eventos
monitor.PublicarLeitura("SEN_PRESSAO_01", 101.3, 150.0); // Normal
monitor.PublicarLeitura("SEN_CALDEIRA_02", 185.7, 150.0); // Alerta

// Desinscrição (- =) para evitar leaks de memória
monitor.AmostraColetada -= painel.OnAmostraRecebida;
Console.WriteLine("\nPainel desinscrito do monitor com sucesso.");

2. Instruções de Compilação e Execução

dotnet new console -n AppEventos -f net8.0
cd AppEventos
dotnet run

3. Saída Esperada no Terminal

=== CAPÍTULO 13: DELEGATES, EVENTOS E PROGRAMAÇÃO REATIVA ===
[LOG ACTION] Delegates Action/Func inicializados.
Func Multiplicador (4.5 * 2): 9
Predicate isPar(42): True

--- Conectando Assinantes ao Monitor de Sensores ---
[Publisher] Publicando leitura do sensor 'SEN_PRESSAO_01': 101.30
  [PAINEL STATUS] Sensor SEN_PRESSAO_01 nominal (101.30).
[Publisher] Publicando leitura do sensor 'SEN_CALDEIRA_02': 185.70
  [PAINEL ALERTA] Sensor SEN_CALDEIRA_02 EXCEDEU LIMIAR! Valor: 185.70 em 05:00:00
  [AUDITORIA] Registrando incidente em banco de dados.

Painel desinscrito do monitor com sucesso.