Desafio C#

Filtro com when e relançamento

Enunciado

Crie um método ProcessarPagamento(decimal valor) que lança SaldoInsuficienteException com a propriedade SaldoAtual. No Main, capture essa exceção usando um filtro when que só trata se SaldoAtual < 100. Caso contrário, relance a exceção com throw;. Use finally para registrar 'Pagamento processado.'

Requisitos

  • A exceção SaldoInsuficienteException deve ter uma propriedade SaldoAtual.
  • O catch deve usar when (ex.SaldoAtual < 100) para tratar apenas saldo baixo.
  • Se o filtro não for atendido, a exceção deve ser relançada com throw; e capturada por um catch externo.
  • O bloco finally deve exibir 'Pagamento processado.'

Código inicial

using System;

public class SaldoInsuficienteException : Exception
{
    public decimal SaldoAtual { get; }
    public SaldoInsuficienteException(decimal saldoAtual)
        : base($"Saldo insuficiente: {saldoAtual:C}")
    {
        SaldoAtual = saldoAtual;
    }
}

class Program
{
    static void ProcessarPagamento(decimal valor)
    {
        // TODO: lançar exceção se valor > saldo (simule saldo = 50)
    }

    static void Main()
    {
        try
        {
            ProcessarPagamento(150);
        }
        catch (SaldoInsuficienteException ex) when (ex.SaldoAtual < 100)
        {
            Console.WriteLine($"Tratado: {ex.Message}");
        }
        catch (SaldoInsuficienteException ex)
        {
            Console.WriteLine($"Não tratado: {ex.Message}");
            throw;
        }
        finally
        {
            Console.WriteLine("Pagamento processado.");
        }
    }
}

Saída esperada

Não tratado: Saldo insuficiente: R$ 50,00
Pagamento processado.

Unhandled exception. SaldoInsuficienteException: Saldo insuficiente: R$ 50,00
   ... (stack trace)
Ver dica

O filtro when avalia a condição antes de entrar no catch. Se falsa, a exceção continua procurando outro catch.

Mostrar solução
using System;

public class SaldoInsuficienteException : Exception
{
    public decimal SaldoAtual { get; }
    public SaldoInsuficienteException(decimal saldoAtual)
        : base($"Saldo insuficiente: {saldoAtual:C}")
    {
        SaldoAtual = saldoAtual;
    }
}

class Program
{
    static void ProcessarPagamento(decimal valor)
    {
        decimal saldo = 50m; // saldo fixo para exemplo
        if (valor > saldo)
            throw new SaldoInsuficienteException(saldo);
        Console.WriteLine("Pagamento aprovado.");
    }

    static void Main()
    {
        try
        {
            ProcessarPagamento(150);
        }
        catch (SaldoInsuficienteException ex) when (ex.SaldoAtual < 100)
        {
            Console.WriteLine($"Tratado: {ex.Message}");
        }
        catch (SaldoInsuficienteException ex)
        {
            Console.WriteLine($"Não tratado: {ex.Message}");
            throw; // relança a exceção original
        }
        finally
        {
            Console.WriteLine("Pagamento processado.");
        }
    }
}

Passo a passo

  1. SaldoInsuficienteException tem a propriedade SaldoAtual para dar contexto ao erro.
  2. ProcessarPagamento simula saldo 50 e lança a exceção se o valor for maior.
  3. No Main, o primeiro catch usa when (ex.SaldoAtual < 100). Como o saldo é 50, a condição é verdadeira e a mensagem 'Tratado' é exibida.
  4. O finally sempre executa, imprimindo 'Pagamento processado.'.
  5. Se o saldo fosse >= 100, o primeiro catch seria ignorado, o segundo catch capturaria e relançaria com throw;, resultando em exceção não tratada.

Por que funciona

O filtro when permite capturar a exceção apenas sob certa condição, evitando if dentro do catch. O throw; relança a exceção preservando o stack trace original, diferente de throw ex; que o reinicia.

Erros comuns

  • Usar throw ex; em vez de throw;: perde-se o stack trace original, dificultando o diagnóstico.
  • Filtro when com efeitos colaterais: o filtro deve ser uma expressão pura; efeitos colaterais podem ser executados duas vezes.
  • Ordem dos catch: capturar o tipo mais genérico primeiro impede que os específicos sejam alcançados.

Outra forma de resolver

Usar if dentro de um único catch para decidir se trata ou relança. O filtro when é preferível por manter a lógica de decisão fora do bloco catch.

Saída esperada

Não tratado: Saldo insuficiente: R$ 50,00
Pagamento processado.

Unhandled exception. SaldoInsuficienteException: Saldo insuficiente: R$ 50,00
   ... (stack trace)