Ejercicio: Creación y inicio de una excepción
A menudo, los desarrolladores necesitan crear e iniciar excepciones desde dentro de un método y, a continuación, detectar esas excepciones más abajo en la pila de llamadas donde se pueden controlar. El control de excepciones le ayuda a garantizar la estabilidad de las aplicaciones.
En este ejercicio, empezará con una aplicación de ejemplo que incluye una posible condición de error dentro de un método llamado. El método actualizado producirá throw una excepción cuando detecte el problema. La excepción se manejará en el bloque catch del código que llama al método. El resultado es una aplicación que proporciona una mejor experiencia de usuario.
Creación de un nuevo proyecto de código
El primer paso es crear un proyecto de código que puede usar durante este módulo.
Abra una nueva instancia de Visual Studio Code.
En el menú Archivo, seleccione Abrir carpeta.
En el cuadro de diálogo Abrir carpeta , vaya a la carpeta escritorio de Windows.
En el cuadro de diálogo Abrir carpeta , seleccione Nueva carpeta.
Asigne a la nueva carpeta el nombre ThrowExceptions101 y, a continuación, seleccione Seleccionar carpeta.
En el menú Terminal, seleccione Nuevo terminal.
Usará un comando de la CLI de .NET para crear una aplicación de consola.
En el símbolo del sistema del panel TERMINAL, escriba el siguiente comando:
dotnet new consoleCierre el panel TERMINAL.
Revisión de una aplicación de ejemplo
Siga estos pasos para cargar y revisar una aplicación de ejemplo.
Abra el archivo Program.cs.
En el menú Vista, seleccione Paleta de comandos.
En el símbolo del sistema, escriba .net: g y, después, seleccione .NET: Generar recursos para compilar y depurar.
Reemplace el contenido del archivo Program.cs por el código siguiente:
// 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; }Tómese un minuto para revisar el código.
Tenga en cuenta que la aplicación realiza las siguientes tareas:
Las instrucciones de nivel superior usan declaraciones
Console.ReadLine()para obtener valores paralowerBoundyupperBound.Las instrucciones de nivel superior pasan
lowerBoundyupperBoundcomo argumentos al llamar alAverageOfEvenNumbersmétodo .El método
AverageOfEvenNumbersrealiza las siguientes tareas:- Declara las variables locales usadas en los cálculos.
- Usa un
forbucle para sumar los números pares entrelowerBoundyupperBound. La suma se almacena ensum. - Cuenta cuántos números se incluyen en la suma. El recuento se almacena en
count. - Almacena el promedio de los números sumados en una variable denominada
average. Se devuelve el valor deaverage.
Las instrucciones de nivel superior imprimen el valor devuelto por
AverageOfEvenNumbersen la consola y, a continuación, pausan la ejecución.
Configure el entorno de depuración
La aplicación de ejemplo lee la entrada del usuario desde la consola. El panel CONSOLA DE DEPURACIÓN no admite la lectura de entradas desde la consola. Debe actualizar el archivo launch.json antes de poder ejecutar esta aplicación en el depurador.
Use la vista EXPLORADOR para abrir el archivo launch.json.
En el archivo launch.json, actualice el atributo de la siguiente manera:
console// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console":"integratedTerminal",El valor predeterminado del atributo
consoleesinternalConsole, que concuerda con el panel CONSOLA DE DEPURACIÓN. El panel CONSOLA DE DEPURACIÓN no admite la entrada de la consola. El valorintegratedTerminalconcuerda con el panel TERMINAL, que admite entradas y salidas de la consola.Guarde los cambios en el archivo launch.json y, a continuación, cierre el archivo.
En el menú Ejecutar de Visual Studio Code, seleccione Iniciar depuración.
Cambie al panel TERMINAL.
En el símbolo del sistema "límite inferior", escriba 3
En el indicador de "límite superior", introduzca 11.
Observe que la aplicación muestra el mensaje siguiente y, a continuación, se pausa:
The average of even numbers between 3 and 11 is 7.Presione Entrar para salir de la aplicación.
Lanzar una excepción en el método AverageOfEvenNumbers
El AverageOfEvenNumbers método espera un límite superior mayor que el límite inferior. Se produce un DivideByZero error si el límite inferior es mayor o igual que el límite superior.
Debe actualizar el AverageOfEvenNumbers método para iniciar una excepción cuando el límite inferior sea mayor o igual que el límite superior.
Dedique un minuto a tener en cuenta cómo desea solucionar el problema.
Una opción es ajustar el cálculo de
averagedentro de untrybloque de código ycatchla excepciónDivideByZerocuando se produce. Puede volver a iniciar la excepción y, a continuación, controlarla en el código de llamada.Otra opción es evaluar los parámetros de entrada antes de iniciar los cálculos. Si
lowerBoundes mayor o igual queupperBound, puede producir una excepción.Evaluar los parámetros e iniciar una excepción antes de iniciar los cálculos es la mejor opción.
Considere qué tipo de excepción se va a producir.
Hay dos tipos de excepciones que se alinean con el problema:
ArgumentOutOfRangeException: solo se debe producir unArgumentOutOfRangeExceptiontipo de excepción cuando el valor de un argumento está fuera del intervalo permitido de valores tal como se define en el método invocado. AunqueAverageOfEvenNumbersno define explícitamente un intervalo permitido paralowerBoundoupperBound, el valor delowerBoundimplica el intervalo permitido paraupperBound.InvalidOperationException: solo se debe producir unInvalidOperationExceptiontipo de excepción cuando las condiciones de funcionamiento de un método no admiten la finalización correcta de una llamada de método determinada. En este caso, los parámetros de entrada del método establecen las condiciones de funcionamiento.
Cuando tenga dos o más tipos de excepciones entre los que elegir, seleccione el tipo de excepción que se ajuste más estrechamente al problema. En este caso, los dos tipos de excepción se alinean con el problema igualmente.
Cuando tenga dos o más tipos de excepción alineados con el problema igualmente, seleccione el tipo de excepción con ámbito más limitado. El
ArgumentOutOfRangeExceptiontipo de excepción se limita a los argumentos pasados al método . ElInvalidOperationExceptiontipo de excepción se limita a las condiciones de funcionamiento del método . En este caso, elArgumentOutOfRangeExceptiontipo de excepción tiene un ámbito más limitado que el tipo deInvalidOperationExceptionexcepción.El
AverageOfEvenNumbersmétodo debe producir unaArgumentOutOfRangeExceptionexcepción.En la parte superior del método
AverageOfEvenNumbers, para detectar el problema de límite superior, actualice el código de la siguiente manera:if (lowerBound >= upperBound) { } int sum = 0;Para crear y producir una excepción
ArgumentOutOfRangeException, actualice el bloque de códigoifde la siguiente manera:if (lowerBound >= upperBound) { throw new ArgumentOutOfRangeException("upperBound", "ArgumentOutOfRangeException: upper bound must be greater than lower bound."); }Esta línea de código inicializa una nueva instancia de la
ArgumentOutOfRangeExceptionclase con el nombre del parámetro de entrada que provoca la excepción y un mensaje de error especificado.
Detectar la excepción en el código de llamada
Siempre que sea posible, las excepciones deben detectarse en el nivel de pila de llamadas donde se pueden controlar. En esta aplicación de ejemplo, los parámetros del AverageOfEvenNumbers método se pueden administrar en el método de llamada (las instrucciones de nivel superior).
Desplácese hacia arriba hasta las declaraciones de nivel superior.
Para incluir la llamada al método
AverageOfEvenNumbersy la instrucciónConsole.WriteLinedentro de un bloque de códigotry, actualice su código de la siguiente manera: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 crear la cláusula asociada
catch, escriba el código siguiente:catch(ArgumentOutOfRangeException ex) { }Dedique un minuto a tener en cuenta cómo puede controlar la excepción.
Para controlar esta excepción, el código debe hacer lo siguiente:
- Explicar el problema al usuario.
- Obtenga un nuevo valor para
upperBound. - Llame a
AverageOfEvenNumbersmediante el nuevoupperBound. - Continúe con
catchla excepción si el nuevoupperBoundproporcionado sigue siendo menor o igual quelowerBound.
Para continuar con
catch, la excepción requiere un bucle. Ya que desea llamar al métodoAverageOfEvenNumbersal menos una vez, se debe usar un ciclodo.Para incluir los
trybloques ycatchdentro de undobucle, actualice el código de la siguiente manera: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) { } }Se requiere una
whileexpresión para definir la condición de salida de undobucle. Es difícil especificar la condición antes de definir el contenido deldobloque de código. Completar elcatchbloque de código le ayudará a definir lawhileexpresión necesaria.Para explicar el problema al usuario y obtener un nuevo
upperBound, actualice el bloque de códigocatchde la siguiente manera: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()); }El bloque de código actualizado
catchdescribe el problema y requiere que el usuario escriba un nuevo límite superior. Sin embargo, ¿qué ocurre si el usuario no tiene un valor de límite superior válido para escribir? ¿Qué ocurre si el usuario necesita salir del bucle en lugar de escribir un valor?Para proporcionar al usuario una opción para salir del bucle en lugar de escribir un nuevo límite superior, actualice
catchel bloque de código de la siguiente manera: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); } }El bloque de código actualizado
catchincluye dos rutas, una ruta de "salida" y una ruta de "nuevo límite superior".Dedique un minuto a tener en cuenta la
whileexpresión necesaria para eldobucle.Si el usuario escribe "Salir" en el indicador, el código debe salir del bucle. Si el usuario escribe un nuevo límite superior, el bucle debe continuar. Una expresión que evalúe un
whileBooleano podría usarse. Por ejemplo:while (exit == false);La expresión propuesta
whileestablecerá el siguiente comportamiento:- El
dobucle continuará iterando siempre que el valor booleanoexitsea igual afalse. - El
dobucle dejará de iterar en cuanto el valor booleanoexitsea igual atrue.
- El
Para crear una instancia de una variable booleana denominada
exit, y usarexitpara establecer la condición de salida del bucledo, actualice su código de la siguiente manera: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);Guarde el código actualizado.
En el menú Ejecutar, seleccione Iniciar depuración.
Cambie al panel TERMINAL.
En el símbolo del sistema "límite inferior", escriba 3
En el indicador de "límite superior", escriba 3.
Observe que la salida siguiente se muestra en el panel 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):En la solicitud para un nuevo límite superior, escriba 11.
Observe que la salida siguiente se muestra en el panel 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.Presione Entrar para salir de la aplicación.
¡Felicidades! Ha producido, detectado y controlado correctamente una excepción.
Resumen
Estos son algunos de los aspectos más importantes que debe recordar de esta unidad:
- Asegúrese de que el entorno de depuración está configurado para admitir los requisitos de la aplicación.
- El código del método debe producir una excepción cuando se detecta un problema o una condición.
- Las excepciones se deben detectar en un nivel de la pila de llamadas donde se pueden resolver.