💻 Exemplos: Capítulo 13: Delegates, Eventos Fortemente Tipados e Lambdas
💻 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.