Exercício - Criar e lançar uma exceção
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.
Abra uma nova instância do Visual Studio Code.
No menu Arquivo, selecione Abrir pasta.
Na caixa de diálogo Abrir pasta , navegue até a pasta da área de trabalho do Windows.
Na caixa de diálogo Abrir pasta , selecione Nova pasta.
Nomeie a nova pasta ThrowExceptions101 e selecione Selecionar pasta.
No menu Terminal, selecione New Terminal (Novo Terminal).
Você usará um comando .NET CLI para criar um novo aplicativo de console.
No prompt de comando do painel TERMINAL, digite o seguinte comando:
dotnet new consoleFeche o painel TERMINAL.
Revisar uma aplicação de exemplo
Use as etapas a seguir para carregar e revisar um aplicativo de exemplo.
Abra o arquivo Program.cs.
No menu Exibir, selecione Paleta de comandos.
No prompt de comando, digite .net: g e selecione .NET: Gerar ativos para compilação e depuração.
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; }Reserve um minuto para rever o código.
Observe que o aplicativo executa as seguintes tarefas:
As instruções de nível superior utilizam
Console.ReadLine()para obter valores paralowerBoundeupperBound.As instruções de nível superior passam
lowerBoundeupperBoundcomo argumentos ao chamar oAverageOfEvenNumbersmétodo.O
AverageOfEvenNumbersmétodo executa as seguintes tarefas:- Declara as variáveis locais usadas nos cálculos.
- Usa um
forloop para somar os números pares entrelowerBoundeupperBound. A soma é armazenada emsum. - Conta quantos números estão incluídos na soma. A contagem é armazenada em
count. - Armazena a média dos números somados em uma variável chamada
average. O valor deaverageé retornado.
As instruções de nível superior imprimem no console o valor retornado por
AverageOfEvenNumberse, 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.
Use o modo de exibição EXPLORER para abrir o arquivo launch.json.
No arquivo launch.json, atualize o
consoleatributo 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
consoleatributo éinternalConsole, que se alinha ao painel DEBUG CONSOLE. Infelizmente, o painel DEBUG CONSOLE não suporta a entrada do console. AintegratedTerminalconfiguração está alinhada ao painel TERMINAL, que suporta entrada e saída do console.Salve as alterações no arquivo launch.json e feche o arquivo.
No menu Executar código do Visual Studio, selecione Iniciar depuração.
Mude para o painel TERMINAL.
Na solicitação "limite inferior", digite 3
No prompt limite superior, introduza 11
Observe que o aplicativo exibe a seguinte mensagem e, em seguida, pausa:
The average of even numbers between 3 and 11 is 7.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.
Reserve um minuto para considerar como você deseja resolver o problema.
Uma opção é envolver o cálculo de
averagedentro de um bloco de códigotrye tratar a exceçãocatchquando ela ocorrerDivideByZero. 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
lowerBoundfor maior ou igual aupperBound, 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.
Considere qual tipo de exceção lançar.
Há dois tipos de exceção que se alinham com o problema:
-
ArgumentOutOfRangeException- UmArgumentOutOfRangeExceptiontipo 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. EmboraAverageOfEvenNumbersnão defina explicitamente um intervalo permitido paralowerBoundouupperBound, o valor delowerBoundimplica o intervalo permitido paraupperBound. -
InvalidOperationException: UmInvalidOperationExceptiontipo 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
ArgumentOutOfRangeExceptiontipo de exceção tem como escopo os argumentos passados para o método. OInvalidOperationExceptiontipo de exceção tem como escopo as condições operacionais do método. Nesse caso, o tipo deArgumentOutOfRangeExceptionexceção tem um escopo mais restrito do que o tipo deInvalidOperationExceptionexceção.O
AverageOfEvenNumbersmétodo deve lançar umaArgumentOutOfRangeExceptionexceção.-
Na parte superior do
AverageOfEvenNumbersmétodo, para detetar o problema do limite superior, atualize o código da seguinte maneira:if (lowerBound >= upperBound) { } int sum = 0;Para criar e lançar uma
ArgumentOutOfRangeExceptionexceção, atualize o bloco deifcó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
ArgumentOutOfRangeExceptionerro 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).
Role para cima até as declarações de nível superior.
Para incluir a chamada de método
AverageOfEvenNumberse a instruçãoConsole.WriteLinedentro de um bloco de códigotry, 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}."); }Para criar a cláusula associada
catch, insira o seguinte código:catch(ArgumentOutOfRangeException ex) { }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
AverageOfEvenNumbersusando o novoupperBound. - Continue com
catcha exceção se o novoupperBoundfornecido ainda for menor ou igual alowerBound.
Continuar para
catcha exceção requer um loop. Como você deseja chamar oAverageOfEvenNumbersmétodo pelo menos uma vez, umdoloop deve ser usado.Para incluir os
tryblocos ecatchdentro de umdoloop, 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
whileexpressão é necessária para definir a condição de saída de umdoloop. É difícil especificar a condição antes que o conteúdo do bloco dedocódigo seja definido. Completar ocatchbloco de código irá ajudá-lo a definir awhileexpressão necessária.Para explicar o problema ao usuário e obter um novo
upperBound, atualize seucatchbloco 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
catchdescreve 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?Para fornecer ao usuário uma opção para sair do loop em vez de inserir um novo limite superior, atualize seu
catchbloco 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
catchinclui dois caminhos, um caminho de "saída" e um caminho de "novo limite superior".Reserve um minuto para considerar a
whileexpressão necessária para odoloop.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
whileexpressão que avalia um booleano pode ser usada. Por exemplo:while (exit == false);A expressão proposta
whileestabelecerá o seguinte comportamento:- o
doloop continuará a iterar enquanto o valor booleanoexitfor igual afalse. - o
doloop irá parar de iterar assim que o Booleanexitfor igual atrue.
- o
Para instanciar uma variável booleana chamada
exit, e usarexitpara definir a condição de saída dodoloop, 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);Salve seu código atualizado.
No menu Executar, selecione Iniciar Depuração.
Mude para o painel TERMINAL.
Na solicitação "limite inferior", digite 3
No pedido para "limite superior", digite 3
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):No prompt para um novo limite superior, digite 11
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.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.