View on GitHub

aulas-programacao-csharp

Materiais de Aula - Programação de Computadores com C#

Tratamento de Exceções

📽 Veja esta vídeo-aula no Youtube


Let’s face it, bad things happen. Networks partition, servers crash, remote endpoints become non-responsive. And when bad things happen, exceptions get thrown. And when exceptions get thrown, people die. Okay, maybe that’s a bit dramatic, but the point is, exceptions are a fact of software development.

Chris Patterson, MassTransit docs


O .NET Core trata situações inesperadas dentro de um programa através do seu mecanismo de exceções. Segundo a documentação, uma exceção é “qualquer condição de erro ou comportamento inesperado encontrado por um programa em execução”, ou seja, erros que não podem ser pegos pelo compilador já que só ocorrem com o programa em execução.

O correto uso das ferramentas para tratamento de exceções do C# é essencial para a criação de programas confiáveis e com uma experiência do usuário adequada.

Capturando uma exceção

Quando um erro ocorre, o C# terá que finalizar o programa, a menos que haja algum tratamento por parte do programa. Fazemos esse tratamento envolvendo o código que poderá gerar o erro em um bloco try...catch:

try
{
    // comando(s) que podem gerar comportamentos inesperados
}
catch
{
    // código que será executado em caso de ocorrência de alguma exceção
}

O bloco try deve conter os comandos que contém erros em potencial. Ele será executado integralmente caso nenhuma exceção seja disparada, e depois seguirá para o primeiro comando após o bloco catch.

O bloco catch só será executado caso alguma exceção ocorra.

Obtendo informações sobre a exceção

Você pode saber mais sobre o erro ocorrido através da seguinte sintaxe:

try
{
    // ...
}
catch (Exception e)
{
    // ...
}

Dessa maneira, e (ou qualquer outro nome que você quiser) é uma variável que contém todas as informações sobre o erro. As mais importantes:

Ex.:

// ...
catch(Exception ex)
{
    Console.WriteLine($"Erro encontrado: {ex.Message}");
    Console.WriteLine($"Tipo da exceção: {ex.GetType()}");
}

Relançando a exceção

Caso seja incluído um bloco catch, a exceção poderá não mais será processada pelo .NET. Nessas situações o programa continuará normalmente, a menos que o programador especifique que a exceção deve ser relançada.

Para relançar uma exceção:

// ...
catch (Exception ex)
{
    // comandos de tratamento de erro...
    throw ex;
}

Lançando uma exceção personalizada

Você pode lançar uma exceção personalizada em qualquer parte do seu código, de acordo com sua necessidade. Escolha o tipo adequado, instancie um objeto de exceção do tipo adequado e use throw.

Ex.:

throw new ArgumentException("O valor informado não é válido.");

Mais detalhes sobre boas práticas no lançamento de exceções na documentação.

Tipos de exceção

O .NET utiliza uma árvore de tipos de exceção. Segue uma lista resumida:

Uma lista detalhada pode ser encontrada na documentação.

Múltiplos catch’s

Você pode utilizar múltiplos blocos catch para tratar diferentes tipos de erros. Use os tipos mais específicos primeiro, já que ao entrar em um bloco, os demais não serão executados. Veja um exemplo abaixo, no programa da vídeo-aula.

Programa da vídeo-aula:

using System;

namespace AulaExcecoes
{
    class Program
    {
        static void Main(string[] args)
        {
            decimal x, y, r;

            try
            {
                // comandos passíveis de exceção
                Console.Write("x = ");
                x = Convert.ToDecimal(Console.ReadLine());

                Console.Write("y = ");
                y = Convert.ToDecimal(Console.ReadLine());

                if (x < 0 || y < 0)
                {
                    throw new ArgumentException("Não são aceitos números negativos.");
                }

                r = x / y;

                Console.WriteLine($"r = {r:N}");
            }
            catch(DivideByZeroException)
            {
                Console.WriteLine("Não é possível dividir por zero.");
            }
            catch(ArgumentException)
            {
                Console.WriteLine("Não são aceitos números negativos.");
            }            
            catch(OverflowException)
            {
                Console.WriteLine("Número inválido.");
            }
            catch(FormatException)
            {
                Console.WriteLine("Número em formato inválido.");
            }
            catch(Exception ex)
            {
                Console.WriteLine($"Erro genérico: {ex.Message}");
                Console.WriteLine($"Tipo: {ex.GetType()}");
                throw ex;
            }
            Console.WriteLine("Final do programa.");
        }
    }
}