💻 Exemplos: Capítulo 14: Tratamento de Exceções, Filtros ‘when’ e o Padrão IDisposable
💻 Exemplos: Capítulo 14: Tratamento de Exceções, Filtros ‘when’ e o Padrão IDisposable
Especialização em Sistemas com C# • Demonstrações Práticas Compiláveis
🎯 Objetivo dos Exemplos
Apresentar a gestão determinística de recursos e exceções no .NET: criação de exceções customizadas de domínio ricas em metadados, filtragem condicional de erros com a cláusula when (sem desenrolar a pilha prematuramente) e a implementação do padrão IDisposable com a declaração moderna using para liberação imediata de recursos do sistema operacional.
1. Código Fonte Completo (Program.cs)
/**
* @file Program.cs
* @brief Exceções customizadas, filtros when e padrão IDisposable determinístico em C# 12.
*/
using System;
Console.WriteLine("=== CAPÍTULO 14: EXCEÇÕES CUSTOMIZADAS E IDISPOSABLE ===");
// 1. Exceção de Domínio Rica em Propriedades
public class TelemetriaException(string mensagem, string sensorId, int codigoGravidade)
: Exception(mensagem)
{
public string SensorId { get; } = sensorId;
public int CodigoGravidade { get; } = codigoGravidade;
}
// 2. Recurso Não Gerenciado com IDisposable
public class RecursoHardwareNativo : IDisposable
{
private bool _disposed;
public string NomeRecurso { get; }
public RecursoHardwareNativo(string nome)
{
NomeRecurso = nome;
Console.WriteLine($"[HARDWARE] Recurso '{NomeRecurso}' alocado no SO.");
}
public void ExecutarOperacaoCritica(int modo)
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (modo == 1)
{
throw new TelemetriaException("Buffer de DMA em curto-circuito", NomeRecurso, codigoGravidade: 500);
}
if (modo == 2)
{
throw new TelemetriaException("Aviso de oscilacao de clock", NomeRecurso, codigoGravidade: 200);
}
Console.WriteLine($" -> Recurso '{NomeRecurso}' operando perfeitamente.");
}
// Padrão Dispose Idiomático
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
Console.WriteLine($"[HARDWARE] Recurso '{NomeRecurso}' liberado e fechado (Dispose).");
GC.SuppressFinalize(this);
}
}
}
// 3. Teste com Declaração 'using' e Filtros 'when'
static void ExecutarCiclo(int modo)
{
Console.WriteLine($"\n--- Iniciando Ciclo de Operacao (Modo {modo}) ---");
// O recurso será destruído incondicionalmente no final deste escopo!
using var dispositivo = new RecursoHardwareNativo($"Device_Canal_{modo}");
try
{
dispositivo.ExecutarOperacaoCritica(modo);
}
catch (TelemetriaException ex) when (ex.CodigoGravidade >= 500)
{
// Filtro captura apenas erros com gravidade alta (>= 500)
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"[FALHA FATAL - when >= 500] Sensor: {ex.SensorId} | Erro: {ex.Message}");
Console.ResetColor();
}
catch (TelemetriaException ex) when (ex.CodigoGravidade < 500)
{
// Filtro captura avisos moderados
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"[AVISO MODERADO - when < 500] Sensor: {ex.SensorId} | Mensagem: {ex.Message}");
Console.ResetColor();
}
}
// Execução
ExecutarCiclo(0); // Sucesso
ExecutarCiclo(2); // Aviso moderado
ExecutarCiclo(1); // Falha crítica
2. Instruções de Compilação e Execução
dotnet new console -n AppExcecoes -f net8.0
cd AppExcecoes
dotnet run
3. Saída Esperada no Terminal
=== CAPÍTULO 14: EXCEÇÕES CUSTOMIZADAS E IDISPOSABLE ===
--- Iniciando Ciclo de Operacao (Modo 0) ---
[HARDWARE] Recurso 'Device_Canal_0' alocado no SO.
-> Recurso 'Device_Canal_0' operando perfeitamente.
[HARDWARE] Recurso 'Device_Canal_0' liberado e fechado (Dispose).
--- Iniciando Ciclo de Operacao (Modo 2) ---
[HARDWARE] Recurso 'Device_Canal_2' alocado no SO.
[AVISO MODERADO - when < 500] Sensor: Device_Canal_2 | Mensagem: Aviso de oscilacao de clock
[HARDWARE] Recurso 'Device_Canal_2' liberado e fechado (Dispose).
--- Iniciando Ciclo de Operacao (Modo 1) ---
[HARDWARE] Recurso 'Device_Canal_1' alocado no SO.
[FALHA FATAL - when >= 500] Sensor: Device_Canal_1 | Erro: Buffer de DMA em curto-circuito
[HARDWARE] Recurso 'Device_Canal_1' liberado e fechado (Dispose).