💻 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).