Exercício - Criar e lançar uma exceção

Concluído

Os desenvolvedores geralmente precisam criar e lançar exceções de dentro de um método e, em seguida, capturar essas exceções mais abaixo na pilha de chamadas, onde elas podem ser tratadas. O tratamento de exceções ajuda a garantir a estabilidade de seus aplicativos.

Neste exercício, você começará com um aplicativo de exemplo que inclui uma condição de erro potencial dentro de um método chamado. O seu método atualizado irá lançar uma exceção quando detetar o problema. A exceção será tratada em um catch bloco do código que chama o método. O resultado é uma aplicação que proporciona uma melhor experiência ao utilizador.

Criar um novo projeto de código

A primeira etapa é criar um projeto de código que você pode usar durante este módulo.

  1. Abra uma nova instância do Visual Studio Code.

  2. No menu Arquivo, selecione Abrir pasta.

  3. Na caixa de diálogo Abrir pasta , navegue até a pasta da área de trabalho do Windows.

  4. Na caixa de diálogo Abrir pasta , selecione Nova pasta.

  5. Nomeie a nova pasta ThrowExceptions101 e selecione Selecionar pasta.

  6. No menu Terminal, selecione New Terminal (Novo Terminal).

    Você usará um comando .NET CLI para criar um novo aplicativo de console.

  7. No prompt de comando do painel TERMINAL, digite o seguinte comando:

    dotnet new console
    
  8. Feche o painel TERMINAL.

Revisar uma aplicação de exemplo

Use as etapas a seguir para carregar e revisar um aplicativo de exemplo.

  1. Abra o arquivo Program.cs.

  2. No menu Exibir, selecione Paleta de comandos.

  3. No prompt de comando, digite .net: g e selecione .NET: Gerar ativos para compilação e depuração.

  4. Substitua o conteúdo do arquivo Program.cs com o seguinte código:

    // Prompt the user for the lower and upper bounds
    Console.Write("Enter the lower bound: ");
    int lowerBound = int.Parse(Console.ReadLine());
    
    Console.Write("Enter the upper bound: ");
    int upperBound = int.Parse(Console.ReadLine());
    
    decimal averageValue = 0;
    
    // Calculate the sum of the even numbers between the bounds
    averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
    // Display the value returned by AverageOfEvenNumbers in the console
    Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
    
    // Wait for user input
    Console.ReadLine();
    
    static decimal AverageOfEvenNumbers(int lowerBound, int upperBound)
    {
        int sum = 0;
        int count = 0;
        decimal average = 0;
    
        for (int i = lowerBound; i <= upperBound; i++)
        {
            if (i % 2 == 0)
            {
                sum += i;
                count++;
            }
        }
    
        average = (decimal)sum / count;
    
        return average;
    }
    
  5. Reserve um minuto para rever o código.

    Observe que o aplicativo executa as seguintes tarefas:

    1. As instruções de nível superior utilizam Console.ReadLine() para obter valores para lowerBound e upperBound.

    2. As instruções de nível superior passam lowerBound e upperBound como argumentos ao chamar o AverageOfEvenNumbers método.

    3. O AverageOfEvenNumbers método executa as seguintes tarefas:

      1. Declara as variáveis locais usadas nos cálculos.
      2. Usa um for loop para somar os números pares entre lowerBound e upperBound. A soma é armazenada em sum.
      3. Conta quantos números estão incluídos na soma. A contagem é armazenada em count.
      4. Armazena a média dos números somados em uma variável chamada average. O valor de average é retornado.
    4. As instruções de nível superior imprimem no console o valor retornado por AverageOfEvenNumbers e, em seguida, pausam a execução.

Configurar o ambiente de depuração

O aplicativo de exemplo lê a entrada do usuário do console. O painel DEBUG CONSOLE não suporta a leitura de entrada do console. Você precisa atualizar o arquivo launch.json antes de executar este aplicativo no depurador.

  1. Use o modo de exibição EXPLORER para abrir o arquivo launch.json.

  2. No arquivo launch.json, atualize o console atributo da seguinte maneira:

    // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
    "console":"integratedTerminal",
    

    O valor padrão para o console atributo é internalConsole, que se alinha ao painel DEBUG CONSOLE. Infelizmente, o painel DEBUG CONSOLE não suporta a entrada do console. A integratedTerminal configuração está alinhada ao painel TERMINAL, que suporta entrada e saída do console.

  3. Salve as alterações no arquivo launch.json e feche o arquivo.

  4. No menu Executar código do Visual Studio, selecione Iniciar depuração.

  5. Mude para o painel TERMINAL.

  6. Na solicitação "limite inferior", digite 3

  7. No prompt limite superior, introduza 11

  8. Observe que o aplicativo exibe a seguinte mensagem e, em seguida, pausa:

    The average of even numbers between 3 and 11 is 7.
    
  9. Para sair do aplicativo, pressione Enter.

Lançar uma exceção no método AverageOfEvenNumbers

O AverageOfEvenNumbers método está esperando um limite superior maior do que o limite inferior. Ocorre um DivideByZero erro se o limite inferior for maior ou igual ao limite superior.

Você precisa atualizar o AverageOfEvenNumbers método para lançar uma exceção quando o limite inferior é maior ou igual ao limite superior.

  1. Reserve um minuto para considerar como você deseja resolver o problema.

    Uma opção é envolver o cálculo de average dentro de um bloco de código try e tratar a exceção catch quando ela ocorrer DivideByZero. Você pode relançar a exceção e, em seguida, manipulá-la no código de chamada.

    Outra opção é avaliar os parâmetros de entrada antes de iniciar os cálculos. Se lowerBound for maior ou igual a upperBound, você pode lançar uma exceção.

    Avaliar os parâmetros e lançar uma exceção antes de iniciar os cálculos é a melhor escolha.

  2. Considere qual tipo de exceção lançar.

    Há dois tipos de exceção que se alinham com o problema:

    • ArgumentOutOfRangeException - Um ArgumentOutOfRangeException tipo de exceção só deve ser lançado quando o valor de um argumento estiver fora do intervalo permitido de valores, conforme definido pelo método invocado. Embora AverageOfEvenNumbers não defina explicitamente um intervalo permitido para lowerBound ou upperBound, o valor de lowerBound implica o intervalo permitido para upperBound.
    • InvalidOperationException: Um InvalidOperationException tipo de exceção só deve ser lançado quando as condições operacionais de um método não suportam a conclusão bem-sucedida de uma chamada de método específica. Neste caso, as condições de funcionamento são estabelecidas pelos parâmetros de entrada do método.

    Quando você tiver dois ou mais tipos de exceção para escolher, selecione o tipo de exceção que se encaixa mais de perto no problema. Neste caso, os dois tipos de exceção estão alinhados à questão igualmente.

    Quando você tiver dois ou mais tipos de exceção alinhados ao problema igualmente, selecione o tipo de exceção com escopo mais restrito. O ArgumentOutOfRangeException tipo de exceção tem como escopo os argumentos passados para o método. O InvalidOperationException tipo de exceção tem como escopo as condições operacionais do método. Nesse caso, o tipo de ArgumentOutOfRangeException exceção tem um escopo mais restrito do que o tipo de InvalidOperationException exceção.

    O AverageOfEvenNumbers método deve lançar uma ArgumentOutOfRangeException exceção.

  3. Na parte superior do AverageOfEvenNumbers método, para detetar o problema do limite superior, atualize o código da seguinte maneira:

    if (lowerBound >= upperBound)
    {
    
    }
    
    int sum = 0;    
    
  4. Para criar e lançar uma ArgumentOutOfRangeException exceção, atualize o bloco de if código da seguinte maneira:

    if (lowerBound >= upperBound)
    {
        throw new ArgumentOutOfRangeException("upperBound", "ArgumentOutOfRangeException: upper bound must be greater than lower bound.");
    }
    

    Essa linha de código inicializa uma nova instância da classe com o nome do parâmetro de entrada que causa a exceção e uma mensagem de ArgumentOutOfRangeException erro especificada.

Capturar a exceção no código de chamada

Sempre que possível, as exceções devem ser detetadas no nível da pilha de chamadas, onde podem ser tratadas. Neste aplicativo de exemplo, os AverageOfEvenNumbers parâmetros do método podem ser gerenciados no método de chamada (as instruções de nível superior).

  1. Role para cima até as declarações de nível superior.

  2. Para incluir a chamada de método AverageOfEvenNumbers e a instrução Console.WriteLine dentro de um bloco de código try, atualize o seu código da seguinte maneira:

    try
    {
        // Calculate the sum of the even numbers between the bounds
        averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
        // Display the result to the user
        Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
    }
    
  3. Para criar a cláusula associada catch , insira o seguinte código:

    catch(ArgumentOutOfRangeException ex)
    {
    
    }
    
  4. Reserve um minuto para considerar como você pode lidar com a exceção.

    Para lidar com essa exceção, seu código precisa fazer o seguinte:

    • Explique o problema ao usuário.
    • Obtenha um novo valor para upperBound.
    • Ligue AverageOfEvenNumbers usando o novo upperBound.
    • Continue com catch a exceção se o novo upperBound fornecido ainda for menor ou igual a lowerBound.

    Continuar para catch a exceção requer um loop. Como você deseja chamar o AverageOfEvenNumbers método pelo menos uma vez, um do loop deve ser usado.

  5. Para incluir os try blocos e catch dentro de um do loop, atualize seu código da seguinte maneira:

    do
    {
        try
        {
            // Calculate the sum of the even numbers between the bounds
            averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
            // Display the result to the user
            Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
        }
        catch (ArgumentOutOfRangeException ex)
        {
    
        }
    }
    

    Uma while expressão é necessária para definir a condição de saída de um do loop. É difícil especificar a condição antes que o conteúdo do bloco de do código seja definido. Completar o catch bloco de código irá ajudá-lo a definir a while expressão necessária.

  6. Para explicar o problema ao usuário e obter um novo upperBound, atualize seu catch bloco de código da seguinte maneira:

    catch (ArgumentOutOfRangeException ex)
    {
        Console.WriteLine("An error has occurred.");
        Console.WriteLine(ex.Message);
        Console.WriteLine($"The upper bound must be greater than {lowerBound}");
        Console.Write($"Enter a new upper bound: ");
        upperBound = int.Parse(Console.ReadLine());
    }
    

    O bloco de código atualizado catch descreve o problema e exige que o usuário insira um novo limite superior. No entanto, e se o usuário não tiver um valor de limite superior válido para inserir? E se o usuário precisar sair do loop em vez de inserir um valor?

  7. Para fornecer ao usuário uma opção para sair do loop em vez de inserir um novo limite superior, atualize seu catch bloco de código da seguinte maneira:

    catch (ArgumentOutOfRangeException ex)
    {
        Console.WriteLine("An error has occurred.");
        Console.WriteLine(ex.Message);
        Console.WriteLine($"The upper bound must be greater than {lowerBound}");
        Console.Write($"Enter a new upper bound (or enter Exit to quit): ");
        string? userResponse = Console.ReadLine();
        if (userResponse.ToLower().Contains("exit"))
        {
    
        }
        else
        {
            upperBound = int.Parse(userResponse);
        }
    }
    

    O bloco de código atualizado catch inclui dois caminhos, um caminho de "saída" e um caminho de "novo limite superior".

  8. Reserve um minuto para considerar a while expressão necessária para o do loop.

    Se o usuário digitar "Exit" no prompt, o código deve sair do loop. Se o usuário inserir um novo limite superior, o loop deve continuar. Uma while expressão que avalia um booleano pode ser usada. Por exemplo:

    while (exit == false);
    

    A expressão proposta while estabelecerá o seguinte comportamento:

    • o do loop continuará a iterar enquanto o valor booleano exit for igual a false.
    • o do loop irá parar de iterar assim que o Boolean exit for igual a true.
  9. Para instanciar uma variável booleana chamada exit, e usar exit para definir a condição de saída do do loop, atualize seu código da seguinte maneira:

    bool exit = false;
    
    do
    {
        try
        {
            // Calculate the sum of the even numbers between the bounds
            averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
            // Display the result to the user
            Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
    
            exit = true;
        }
        catch (ArgumentOutOfRangeException ex)
        {
            Console.WriteLine("An error has occurred.");
            Console.WriteLine(ex.Message);
            Console.WriteLine($"The upper bound must be greater than {lowerBound}");
            Console.Write($"Enter a new upper bound (or enter Exit to quit): ");
            string? userResponse = Console.ReadLine();
            if (userResponse.ToLower().Contains("exit"))
            {
                exit = true;
            }
            else
            {
                exit = false;
                upperBound = int.Parse(userResponse);
            }
        }    
    } while (exit == false);
    
  10. Salve seu código atualizado.

  11. No menu Executar, selecione Iniciar Depuração.

  12. Mude para o painel TERMINAL.

  13. Na solicitação "limite inferior", digite 3

  14. No pedido para "limite superior", digite 3

  15. Observe que a seguinte saída é exibida no painel TERMINAL:

    Enter the lower bound: 3
    Enter the upper bound: 3
    An error has occurred.
    ArgumentOutOfRangeException: upper bound must be greater than lower bound. (Parameter 'upperBound')
    The upper bound must be greater than 3
    Enter a new upper bound (or enter Exit to quit):
    
  16. No prompt para um novo limite superior, digite 11

  17. Observe que a seguinte saída é exibida no painel TERMINAL:

    Enter the lower bound: 3
    Enter the upper bound: 3
    An error has occurred.
    ArgumentOutOfRangeException: upper bound must be greater than lower bound. (Parameter 'upperBound')
    The upper bound must be greater than 3
    Enter a new upper bound (or enter Exit to quit): 11
    The average of even numbers between 3 and 11 is 7.
    
  18. Para sair do aplicativo, pressione Enter.

Parabéns! Você jogou, pegou e lidou com uma exceção com sucesso.

Recapitulação

Aqui estão algumas coisas importantes para lembrar desta unidade:

  • Certifique-se de que seu ambiente de depuração esteja configurado para suportar os requisitos do aplicativo.
  • O código do método deve lançar uma exceção quando um problema ou condição é detetado.
  • As exceções devem ser detetadas em um nível na pilha de chamadas em que possam ser resolvidas.