Ejercicio: Creación y inicio de una excepción

Completado

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.

  1. Abra una nueva instancia de Visual Studio Code.

  2. En el menú Archivo, seleccione Abrir carpeta.

  3. En el cuadro de diálogo Abrir carpeta , vaya a la carpeta escritorio de Windows.

  4. En el cuadro de diálogo Abrir carpeta , seleccione Nueva carpeta.

  5. Asigne a la nueva carpeta el nombre ThrowExceptions101 y, a continuación, seleccione Seleccionar carpeta.

  6. En el menú Terminal, seleccione Nuevo terminal.

    Usará un comando de la CLI de .NET para crear una aplicación de consola.

  7. En el símbolo del sistema del panel TERMINAL, escriba el siguiente comando:

    dotnet new console
    
  8. Cierre el panel TERMINAL.

Revisión de una aplicación de ejemplo

Siga estos pasos para cargar y revisar una aplicación de ejemplo.

  1. Abra el archivo Program.cs.

  2. En el menú Vista, seleccione Paleta de comandos.

  3. En el símbolo del sistema, escriba .net: g y, después, seleccione .NET: Generar recursos para compilar y depurar.

  4. 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;
    }
    
  5. Tómese un minuto para revisar el código.

    Tenga en cuenta que la aplicación realiza las siguientes tareas:

    1. Las instrucciones de nivel superior usan declaraciones Console.ReadLine() para obtener valores para lowerBound y upperBound.

    2. Las instrucciones de nivel superior pasan lowerBound y upperBound como argumentos al llamar al AverageOfEvenNumbers método .

    3. El método AverageOfEvenNumbers realiza las siguientes tareas:

      1. Declara las variables locales usadas en los cálculos.
      2. Usa un for bucle para sumar los números pares entre lowerBound y upperBound. La suma se almacena en sum.
      3. Cuenta cuántos números se incluyen en la suma. El recuento se almacena en count.
      4. Almacena el promedio de los números sumados en una variable denominada average. Se devuelve el valor de average .
    4. Las instrucciones de nivel superior imprimen el valor devuelto por AverageOfEvenNumbers en 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.

  1. Use la vista EXPLORADOR para abrir el archivo launch.json.

  2. 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 console es internalConsole, que concuerda con el panel CONSOLA DE DEPURACIÓN. El panel CONSOLA DE DEPURACIÓN no admite la entrada de la consola. El valor integratedTerminal concuerda con el panel TERMINAL, que admite entradas y salidas de la consola.

  3. Guarde los cambios en el archivo launch.json y, a continuación, cierre el archivo.

  4. En el menú Ejecutar de Visual Studio Code, seleccione Iniciar depuración.

  5. Cambie al panel TERMINAL.

  6. En el símbolo del sistema "límite inferior", escriba 3

  7. En el indicador de "límite superior", introduzca 11.

  8. 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.
    
  9. 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.

  1. Dedique un minuto a tener en cuenta cómo desea solucionar el problema.

    Una opción es ajustar el cálculo de average dentro de un try bloque de código y catch la excepción DivideByZero cuando 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 lowerBound es mayor o igual que upperBound, 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.

  2. 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 un ArgumentOutOfRangeException tipo 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. Aunque AverageOfEvenNumbers no define explícitamente un intervalo permitido para lowerBound o upperBound, el valor de lowerBound implica el intervalo permitido para upperBound.
    • InvalidOperationException: solo se debe producir un InvalidOperationException tipo 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 ArgumentOutOfRangeException tipo de excepción se limita a los argumentos pasados al método . El InvalidOperationException tipo de excepción se limita a las condiciones de funcionamiento del método . En este caso, el ArgumentOutOfRangeException tipo de excepción tiene un ámbito más limitado que el tipo de InvalidOperationException excepción.

    El AverageOfEvenNumbers método debe producir una ArgumentOutOfRangeException excepción.

  3. 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;    
    
  4. Para crear y producir una excepción ArgumentOutOfRangeException, actualice el bloque de código if de 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 ArgumentOutOfRangeException clase 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).

  1. Desplácese hacia arriba hasta las declaraciones de nivel superior.

  2. Para incluir la llamada al método AverageOfEvenNumbers y la instrucción Console.WriteLine dentro de un bloque de código try, 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}.");
    }
    
  3. Para crear la cláusula asociada catch , escriba el código siguiente:

    catch(ArgumentOutOfRangeException ex)
    {
    
    }
    
  4. 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 AverageOfEvenNumbers mediante el nuevo upperBound.
    • Continúe con catch la excepción si el nuevo upperBound proporcionado sigue siendo menor o igual que lowerBound.

    Para continuar con catch, la excepción requiere un bucle. Ya que desea llamar al método AverageOfEvenNumbers al menos una vez, se debe usar un ciclo do.

  5. Para incluir los try bloques y catch dentro de un do bucle, 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 while expresión para definir la condición de salida de un do bucle. Es difícil especificar la condición antes de definir el contenido del do bloque de código. Completar el catch bloque de código le ayudará a definir la while expresión necesaria.

  6. Para explicar el problema al usuario y obtener un nuevo upperBound, actualice el bloque de código catch 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: ");
        upperBound = int.Parse(Console.ReadLine());
    }
    

    El bloque de código actualizado catch describe 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?

  7. Para proporcionar al usuario una opción para salir del bucle en lugar de escribir un nuevo límite superior, actualice catch el 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 catch incluye dos rutas, una ruta de "salida" y una ruta de "nuevo límite superior".

  8. Dedique un minuto a tener en cuenta la while expresión necesaria para el do bucle.

    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 while Booleano podría usarse. Por ejemplo:

    while (exit == false);
    

    La expresión propuesta while establecerá el siguiente comportamiento:

    • El do bucle continuará iterando siempre que el valor booleano exit sea igual a false.
    • El do bucle dejará de iterar en cuanto el valor booleano exit sea igual a true.
  9. Para crear una instancia de una variable booleana denominada exit, y usar exit para establecer la condición de salida del bucle do, 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);
    
  10. Guarde el código actualizado.

  11. En el menú Ejecutar, seleccione Iniciar depuración.

  12. Cambie al panel TERMINAL.

  13. En el símbolo del sistema "límite inferior", escriba 3

  14. En el indicador de "límite superior", escriba 3.

  15. 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):
    
  16. En la solicitud para un nuevo límite superior, escriba 11.

  17. 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.
    
  18. 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.