C# - Criando exceções personalizadas
Hoje veremos como criar exceções personalizadas usando a linguagem C#. |
Uma exceção é uma condição de erro ou um comportamento inesperado que ocorre durante a execução de um código em um programa.
Na linguagem C#
uma exceção pode ser definida como um objeto que herda da classe
System.Exception que é criado ou lançado quando
ocorre uma condição de erro e que contém informações que devem ajudar a
identificar o problema ocorrido.
Ao ocorrer uma exceção ela é lançada da área do código onde ocorreu o problema e
passada para cima na pilha de chamadas de método em execução até que seja
tratada ou que o programa seja encerrado.
A plataforma .NET
inclui classes de exceção internas para cada erro possível, e, a classe
Exception é a classe base de todas as classes de exceção.
A seguir temos a hierarquia de classes de exceções (resumida) do .NET :
No entanto, em alguns casos, quando nenhuma delas atende às nossas necessidades,
podemos criar nossas próprias exceções personalizadas derivando da classe
Exception. Desta forma para criar uma classe de
exceção personalizada basta criar a sua classe derivando da classe
System.Exception, e, isso é bem fácil de ser
implementado.
Basta seguir duas recomendações :
1 - A recomendação é finalizar o nome da exceção criada
com a palavra "Exception"
2 - Implementar os três construtores comuns
A seguir temos um exemplo de uma classe de exceção personalizada chamada
MinhaExcecaoException
que herda de Exception :
public class
MinhaExcecaoException : Exception { public MinhaExcecaoException() { } public MinhaExcecaoException(string message) : base(message) { } public MinhaExcecaoException(string message, Exception inner) : base(message, inner) { } } |
Observe que o nome da exceção termina com o sufixo Exception e que ela implementa os 3 construtores :
Após criar a classe de exceção personalizada podemos usar a classe da mesma forma que usamos uma classe de exceção da plataforma .NET e assim podemos então em um bloco try-catch e lançar a exceção usando a instrução throw e no bloco catch capturar a exceção da mesma forma que fazemos com qualquer outra exceção.
Para o exemplo acima podemos então fazer o tratamento de erros assim:
try { //codigo throw new MinhaExcecaoException("Esta é a minha exceção"); } catch (MinhaExcecaoException ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } |
Como exemplo vamos criar um projeto Console no .NET 7.0 e criar uma classe Conta com 3 propriedades: Numero, Titular e Saldo e os métodos Depositar e Sacar :
public class Conta { public Conta(int numero, string? titular, decimal saldo) { Numero = numero; Titular = titular; Saldo = saldo; } public int Numero { get; set; } public string? Titular { get; set;} public decimal Saldo { get; set; } public decimal Depositar(decimal valor) { Saldo += valor; Console.WriteLine($"Depositou : {valor}"); return Saldo; } public decimal Sacar(decimal valor) { Console.WriteLine($"Sacou : {valor}"); if (Saldo < valor) throw new ArgumentException("Saldo Insuficiente"); Saldo -= valor; return Saldo; } public override string ToString() => $"Conta : {Numero} : {Titular} - Saldo={Saldo}\n"; } |
Note que aqui estamos lançando um ArgumentoException, que é um exceção da plataforma .NET, quando o valor do saque for maior que o saldo.
Vamos agora criar uma classe no projeto personalizada chamada SaldoInsuficienteExcepton para tratar esta exceção de forma específica.
public class SaldoInsuficienteException : Exception
{
public SaldoInsuficienteException() { }
public SaldoInsuficienteException(string? message)
: base(message)
{ }
public SaldoInsuficienteException(string? message, Exception? innerException)
: base(message, innerException)
{ }
public SaldoInsuficienteException(decimal saque, decimal saldo)
: base($"\nException: Valor do saque {saque} é superior ao saldo {saldo}")
{ }
public override string HelpLink
{
get
{
return "Info: https://rb.gy/clgqbv";
}
}
}
|
Neste código criamos a exceção personalizada que herda de Exception e que implementa os construtores padrão. Para incrementar um pouco o código implementamos um construtor que vai receber os argumentos do valor do saque e do saldo e exibir uma mensagem ao usuário.
Também sobrescrevemos a propriedade HelpLink definindo um link de ajuda para a exceção.
Para usar esta implementação vamos alterar o código da classe Program e implementar o tratamento de erros tratando a exceção SaldoInsuficienteException em um bloco try-catch:
using _06ExcecoesPersonalizadas;
Conta conta1 = new Conta(100, "Maria", 100m);
try
{
Console.WriteLine(conta1.ToString());
conta1.Depositar(100);
Console.WriteLine($"Saldo : {conta1.Saldo}");
conta1.Sacar(300);
Console.WriteLine($"Saldo : {conta1.Saldo}");
}
catch(SaldoInsuficienteException ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.HelpLink);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.ReadKey();
public class Conta
{
public Conta(int numero, string? titular, decimal saldo)
{
Numero = numero;
Titular = titular;
Saldo = saldo;
}
public int Numero { get; set; }
public string? Titular { get; set; }
public decimal Saldo { get; set; }
public decimal Depositar(decimal valor)
{
Saldo += valor;
Console.WriteLine($"Depositou : {valor}");
return Saldo;
}
public decimal Sacar(decimal valor)
{
Console.WriteLine($"Sacou : {valor}");
if (Saldo < valor)
throw new SaldoInsuficienteException(valor,Saldo);
Saldo -= valor;
return Saldo;
}
public override string ToString()
{
return $"Conta : {Numero} : {Titular} - Saldo={Saldo}";
}
}
|
Note que agora extamos lançando a exceção SaldoInsuficienteException usando a instrução throw e que estamos usando o construtor passando o valor do saque e do saldo.
Executando o código iremos obter o seguinte resultado no console:
Podemos ainda sobrescrever a propriedade Message da classe Exception em nossa exceção personalizada :
... public override string Message { get { return "\nNão existe saldo suficiente para o valor do saque"; } } ... |
Para concluir seguem algumas recomendações importantes a considerar quando da criação de uma exceção personalizada :
E estamos conversados...
"Todas as
coisas são puras para os puros, mas nada é puro para os contaminados e infiéis;
antes o seu entendimento e consciência estão contaminados."
Tito 1:15
Referências:
NET - Unit of Work - Padrão Unidade de ...