Examen de excepciones y el proceso de control de excepciones
- 11 minutos
Los errores en tiempo de ejecución de una aplicación de C# se administran mediante un mecanismo denominado excepciones. Las excepciones proporcionan una forma estructurada, uniforme y segura en cuanto a tipos de controlar las condiciones de error a nivel de sistema y a nivel de aplicación. El entorno de ejecución de .NET o el código de una aplicación generan excepciones.
Escenarios comunes que requieren control de excepciones
Hay varios escenarios de programación que requieren el control de excepciones. Muchos de estos escenarios implican alguna forma de adquisición de datos. Aunque algunos de los escenarios implican técnicas de codificación que están fuera del ámbito de este entrenamiento, todavía merece la pena tener en cuenta.
Entre los escenarios comunes que requieren control de excepciones se incluyen:
Entrada de usuario: las excepciones pueden producirse cuando el código procesa la entrada del usuario. Por ejemplo, las excepciones se producen cuando el valor de entrada está en el formato incorrecto o fuera del intervalo.
Procesamiento y cálculos de datos: las excepciones pueden producirse cuando el código realiza cálculos de datos o conversiones. Por ejemplo, las excepciones se producen cuando el código intenta dividir por cero, convertir en un tipo no admitido o asignar un valor que está fuera del intervalo.
Operaciones de entrada y salida de archivos: las excepciones pueden producirse cuando el código lee o escribe en un archivo. Por ejemplo, las excepciones se producen cuando el archivo no existe, el programa no tiene permiso para acceder al archivo o el archivo está en uso por otro proceso.
Operaciones de base de datos: las excepciones pueden producirse cuando el código interactúa con una base de datos. Por ejemplo, las excepciones se producen cuando se pierde la conexión de base de datos, se produce un error de sintaxis en una instrucción SQL o se produce una infracción de restricción.
Comunicación de red: las excepciones pueden producirse cuando el código se comunica a través de una red. Por ejemplo, las excepciones se producen cuando se pierde la conexión de red, se produce un tiempo de espera o el servidor remoto devuelve un error.
Otros recursos externos: se pueden producir excepciones cuando el código se comunica con otros recursos externos. Los servicios web, las API REST o las bibliotecas de terceros pueden producir excepciones por diversos motivos. Por ejemplo, se producen excepciones debido a problemas de conexiones de red, datos con formato incorrecto, etc.
Palabras clave de control de excepciones, bloques de código y patrones
El control de excepciones en C# se implementa mediante las trypalabras clave , catchy finally . Cada una de estas palabras clave tiene un bloque de código asociado y se puede usar para satisfacer un objetivo específico en el enfoque del control de excepciones. Por ejemplo:
try
{
// try code block - code that may generate an exception
}
catch
{
// catch code block - code to handle an exception
}
finally
{
// finally code block - code to clean up resources
}
Nota:
El lenguaje C# también permite que el código genere un objeto de excepción mediante la throw palabra clave . Los escenarios de control de excepciones que incluyen el uso de la throw palabra clave para generar excepciones se tratan en un módulo independiente de Microsoft Learn.
El bloque de código try contiene el código protegido que puede producir una excepción. Si el código de un try bloque produce una excepción, la excepción se controla mediante un bloque correspondiente catch .
El bloque de código catch contiene el código que se ejecuta cuando se detecta una excepción. El catch bloque puede controlar la excepción, registrarla o ignorarla. Es posible configurar un catch bloque para que se ejecute cuando se produzca cualquier tipo de excepción, o solo cuando se produzca un tipo de excepción específico.
El finally bloque de código contiene código que ejecuta si se produce o no una excepción. El finally bloque se usa a menudo para limpiar los recursos asignados en un try bloque. Por ejemplo, asegurándose de que una variable tiene asignado el valor correcto o necesario.
El control de excepciones en una aplicación de C# se implementa normalmente mediante uno o varios de los patrones siguientes:
- El
try-catchpatrón consta de untrybloque seguido de una o variascatchcláusulas. Cadacatchbloque se usa para especificar controladores para distintas excepciones. - El
try-finallypatrón consta de untrybloque seguido de unfinallybloque. Por lo general, las instrucciones de un bloquefinallyse ejecutan cuando el control deja una instruccióntry. - El
try-catch-finallypatrón implementa los tres tipos de bloques de control de excepciones. Un escenario común para eltry-catch-finallypatrón es cuando los recursos se obtienen y usan en untrybloque, las circunstancias excepcionales se administran en uncatchbloque y los recursos se liberan o se administran de otro modo en elfinallybloque.
¿Cómo se representan las excepciones en el código?
Las excepciones se representan en el código como objetos, lo que significa que son una instancia de una clase. La biblioteca de clases de .NET proporciona clases de excepción a las que se accede en el código igual que otras clases de .NET. Otro ejemplo de la clase .NET que se usa como objeto en el código es la Random clase (que se usa para crear números aleatorios).
Más precisamente, las excepciones son tipos, representados por clases que se derivan en última instancia de System.Exception. Una clase de excepción derivada de Exception incluye información que identifica el tipo de excepción y contiene propiedades que proporcionan detalles sobre la excepción. Más adelante en este módulo se incluye un examen más detallado de la Exception clase.
Una instancia en tiempo de ejecución de una clase se conoce generalmente como un objeto, por lo que las excepciones a menudo se conocen como objetos de excepción.
Nota:
Aunque a veces se usan indistintamente, una clase y un objeto son cosas diferentes. Una clase define un tipo de objeto, pero no es un propio objeto. Un objeto es una entidad concreta basada en una clase.
Proceso de control de excepciones
Cuando se produce una excepción, el entorno de ejecución de .NET busca la cláusula más catch cercana que puede controlar la excepción. El proceso comienza con el método que provocó la excepción. En primer lugar, se examina el método para ver si el código que provocó la excepción está dentro de un try bloque de código. Si el código está dentro del bloque de código try, las catch cláusulas asociadas a la try instrucción se consideran en orden. Si las cláusulas catch no pueden controlar la excepción, se busca el método que llamó al método actual. Este método se examina para determinar si la llamada al método (al primer método) está dentro de un try bloque de código. Si la llamada está dentro de un try bloque de código, se consideran las cláusulas asociadas catch . Este proceso de búsqueda continúa hasta que se encuentra una catch cláusula que puede controlar la excepción actual.
Una vez que se encuentra una catch cláusula que puede controlar la excepción, el tiempo de ejecución se prepara para transferir el control a la primera instrucción del catch bloque. Sin embargo, antes de que comience la ejecución del catch bloque, el tiempo de ejecución ejecuta los finally bloques asociados a las try instrucciones encontradas durante la búsqueda. Si se encuentra más de un finally bloque, se ejecutan en orden, empezando por el más cercano al código que provocó la excepción.
Si no se encuentra ninguna catch cláusula para controlar la excepción, el tiempo de ejecución finaliza la aplicación y muestra un mensaje de error al usuario.
Tenga en cuenta el ejemplo de código siguiente que incluye un try-finally patrón anidado dentro de un try-catch patrón:
try
{
// Step 1: code execution begins
try
{
// Step 2: an exception occurs here
}
finally
{
// Step 4: the system executes the finally code block associated with the try statement where the exception occurred
}
}
catch // Step 3: the system finds a catch clause that can handle the exception
{
// Step 5: the system transfers control to the first line of the catch code block
}
En este ejemplo, se produce el siguiente proceso:
- La ejecución comienza en el bloque de código de la instrucción externa
try. - Se produce una excepción en el bloque de código de la declaración interna
try. - El tiempo de ejecución busca la cláusula
catchasociada a la instruccióntryexterna. - Antes de que el tiempo de ejecución transfiera el control a la primera línea del bloque de código
catch, ejecuta la cláusulafinallyasociada a la instrucción internatry. - A continuación, el runtime transfiere el control a la primera línea del
catchbloque de código y ejecuta el código que controla la excepción.
En este ejemplo sencillo, los patrones anidados try-catch y try-finally residen dentro de un único método, pero múltiples patrones try-catch y try-finally podrían distribuirse entre métodos que llaman a otros métodos.
Manejo de excepciones y la pila de llamadas
A menudo verá el término "desenredado de la pila de llamadas" cuando lea sobre el control de excepciones y el proceso de control de excepciones. Para comprender este término, debe comprender la pila de llamadas y cómo se usa para realizar el seguimiento de la "pila" de llamadas de método durante la ejecución del código.
Puede pensar en la pila de llamadas como una torre de bloques. Cuando construyes una torre, empiezas con solo un bloque. Cada vez que agregas un bloque a la torre, lo colocas encima de los bloques existentes. Cuando la aplicación comienza a ejecutarse en el depurador, el punto de entrada a la aplicación es la primera capa agregada a la pila de llamadas (el primer bloque de la torre). Cada vez que un método llama a otro método, el nuevo método se agrega a la parte superior de la pila. Cuando el código sale de un método, el método se quita de la pila de llamadas.
Nota:
Para una aplicación de consola, el punto de entrada de tu aplicación son las declaraciones de nivel superior. En la pila de llamadas de Visual Studio Code, este punto de entrada se conoce como el método Main.
El desenredado de la pila de llamadas es el proceso que usa el entorno de ejecución de .NET cuando un programa de C# encuentra un error. Es el mismo proceso que acabas de revisar.
Regresando a la analogía de la torre de bloques, cuando necesites quitar un bloque de la torre, comienzas desde la parte superior y quitas cada bloque hasta llegar al que necesitas. Este proceso es similar a cómo funciona el desenredado de la pila de llamadas, donde cada capa de llamada de la pila es como un bloque en la torre. Cuando el entorno de ejecución necesita desenredar la pila de llamadas, empieza desde la parte superior y quita cada capa de llamada hasta que alcanza la que tiene lo que necesita. En este caso, el método que necesita es la capa de llamada que tiene una cláusula catch capaz de manejar la excepción que se produjo.
Resumen
Estos son algunos de los aspectos más importantes que debe recordar de esta unidad:
- Entre los escenarios comunes que pueden requerir el control de excepciones se incluyen la entrada del usuario, el procesamiento de datos, las operaciones de E/S de archivos, las operaciones de base de datos y la comunicación de red.
- El control de excepciones en C# se implementa mediante
trylas palabras clave ,catchyfinally. Cada palabra clave tiene un bloque de código asociado que sirve para un propósito específico. - Las excepciones se representan como tipos y se derivan de la
System.Exceptionclase en .NET. Las excepciones contienen información que identifica el tipo de excepción y las propiedades que proporcionan detalles adicionales. - Cuando se produce una excepción, el entorno de ejecución de .NET busca la cláusula más
catchcercana que puede controlarla. La búsqueda comienza con el método donde se produjo la excepción y baja hacia la pila de llamadas si es necesario.