TRY CATCH FINALLY EN CSHARP | C# .NET

Manejo de Excepciones en C# .NET

Es indiscutible que por mucho que nos lo propongamos, nuestras aplicaciones no estarán libres de errores, y no nos referimos a errores sintácticos, ya que, afortunadamente, el IDE (Integrated Development Envirnment, entorno de desarrollo integrado) de Visual Studio nos avisará de cualquier error sintáctico e incluso de cualquier asignación no válida, pero de lo que no nos avisará, como es lógico, será de los errores que se produzcan en tiempo de ejecución. Para estos casos, C# pone a nuestra disposición el manejo de excepciones, veamos pues cómo utilizarlo.


 


En Visual C# .NET se utiliza un tratamiento estructurado de excepciones, de esta forma podemos detectar los errores que se produzcan en nuestras aplicaciones de una forma más "ordenada".

Manejo de excepciones estructuradas


Las excepciones en C# las podemos controlar usando las instrucciones try / catch / finally. Estas instrucciones realmente son bloques de instrucciones, y por tanto estarán delimitadas con un par de llaves.
Cuando queramos controlar una parte del código que puede producir un error lo incluimos dentro del bloque try, si se produce un error, éste lo podemos detectar en el bloque catch, por último, independientemente de que se produzca o no una excepción, podemos ejecutar el código que incluyamos en el bloque finally.
Cuando creamos una estructura de control de excepciones no estamos obligados a usar los tres bloques, aunque el primero: try si es necesario, ya que es el que le indica al compilador que tenemos intención de controlar los errores que se produzcan. Por tanto, podemos crear un "manejador" de excepciones usando los tres bloques, usando try y catch o usando try y finally.
Veamos ahora con más detalle cada uno de estos bloques y que es lo que podemos hacer en cada uno de ellos.

Bloque try


En este bloque incluiremos el código en el que queremos comprobar los errores.
El código a usar será un código normal, es decir, no tenemos que hacer nada en especial, ya que en el momento que se produzca el error se usará (si hay) el código del bloque catch.

Bloque catch


Si se produce una excepción, ésta la capturamos en un bloque catch.
En el bloque catch podemos indicar que tipo de excepción queremos capturar, para ello usaremos una variable de tipo Exception, la cual puede ser del tipo de error específico que queremos controlar o de un tipo genérico.

Por ejemplo, si sabemos que nuestro código puede producir un error al trabajar con ficheros, podemos usar un código como éste:

try
{
    // código para trabajar con ficheros, etc.
}
catch(System.IO.IOException ex)
{
    // el código a ejecutar cuando se produzca ese error
}

Si nuestra intención es capturar todos los errores que se produzcan, es decir, no queremos hacer un filtro con errores específicos, podemos usar la clase Exception como tipo de excepción a capturar. La clase Exception es la más genérica de todas las clases para manejo de excepciones, por tanto, capturará todas las excepciones que se produzcan.

try
{
    // código que queremos controlar
}
catch(System.Exception ex)
{
    // el código a ejecutar cuando se produzca cualquier error
}

Aunque si no vamos usar la variable indicada en el bloque Catch, pero queremos que no se detenga la aplicación cuando se produzca un error, podemos hacerlo de esta forma:

try
{
    // código que queremos controlar
}
catch
{
    // el código a ejecutar cuando se produzca cualquier error
}

La variable indicada en el bloque catch la podemos usar para mostrar un mensaje al usuario o para obtener información extra sobre el error, pero no siempre vamos a hacer uso de esa variable, en ese caso podemos utilizar el código anterior, en el que no se usa una variable y tampoco se indica el tipo de error que queremos interceptar. Pero es posible que nuestra intención sea capturar errores de un tipo concreto sin necesidad de utilizar una variable, en ese caso podemos crear un bloque catch como el siguiente, en el que solo se indica el tipo de excepción:

try
{
    // código que queremos controlar
}
catch(FormatException)
{
    // interceptar los errores del tipo FormatException
}

Varias capturas de errores en un mismo bloque try/catch


En un mismo try/catch podemos capturar diferentes tipos de errores, para ello podemos incluir varios bloques catch, cada uno de ellos con un tipo de excepción diferente.

Es importante tener en cuenta que cuando se produce un error y usamos varios bloques catch, el CLR de .NET buscará la captura que mejor se adapte al error que se ha producido, pero siempre lo hará examinando los diferentes bloques catch que hayamos indicado empezando por el indicado después del bloque try, por tanto deberíamos poner las más genéricas al final, de forma que siempre nos aseguremos de que las capturas de errores más específicas se intercepten antes que las genéricas.

Aunque el propio compilador de C# detectará si hay capturas de errores genéricas antes que las más específicas, avisándonos de ese hecho.
En el siguiente código capturamos un error específico y también uno genérico, con idea de que tengamos siempre controlado cualquier error que se produzca:

try
{
    // código que queremos controlar
}
catch(FormatException)
{
    // captura de error de formato
}
catch(Exception ex)
{
    // captura del resto de errores
}

Bloque finally


En este bloque podemos indicar las instrucciones que queremos que se ejecuten, se produzca o no una excepción. De esta forma nos aseguramos de que siempre se ejecutará un código, por ejemplo, para liberar recursos, se haya producido un error o no.

En este código tenemos tres capturas de errores diferentes y un bloque finally que siempre se ejecutará, se produzca o no un error:

int i, j;
//
try
{
    Console.Write("Un numero ");
    i = Convert.ToInt32(Console.ReadLine());
    Console.Write("Otro numero ");
    j = Convert.ToInt32(Console.ReadLine());
 
    int r = i / j;
 
    Console.WriteLine("El resultado es: {0}", r);
}
catch (FormatException)
{
    Console.WriteLine("No es un número válido");
    // Salimos de la función, pero se ejecutará el finally
    return;
}
catch (DivideByZeroException)
{
    Console.WriteLine("La división por cero no está permitida.");
}
catch (Exception ex)
{
    // Captura del resto de excepciones
    Console.WriteLine(ex.Message);
}
finally
{
    // Este código siempre se ejecutará
    Console.WriteLine("Se acabó");
}

Nota:
Hay que tener en cuenta de que incluso si usamos return dentro de un bloque de control de errores, se ejecutará el código indicado en el bloque finally.


Captura de errores no controlados


Como es lógico, si no controlamos las excepciones que se puedan producir en nuestras aplicaciones, éstas serán inicialmente controladas por el propio runtime de .NET, en estos casos la aplicación se detiene y se muestra el error al usuario. Pero esto es algo que no deberíamos consentir, por tanto, siempre deberíamos detectar todos los errores que se produzcan en nuestras aplicaciones, pero a pesar de que lo intentemos, es muy probable que no siempre podamos conseguirlo.

Una forma de hacerlo es iniciando nuestra aplicación dentro de un bloque try/catch, de esta forma, cuando se produzca el error, se capturará en ese bloque catch, porque cuando el runtime de .NET se encuentra con una excepción, lo que hace es revisar "la pila" de llamadas y buscar algún try/catch, si lo encuentra, lo utiliza, y si no lo encuentra, se encarga de lanzar la excepción deteniendo el programa.

Esto es importante saberlo, no ya por detectar esos errores que no hemos tenido la previsión de controlar, sino porque es posible que, si un error se produce dentro de un método en el que no hay captura de errores, pero antes de llamar a ese método hemos usado un try/catch, el error será interceptado por ese catch, aunque posiblemente ni siquiera lo pusimos pensando que podía capturar errores producidos en otros niveles más profundos de nuestra aplicación.


*** EJEMPLOS DEL VIDEO ***

EJEMPLO 1



EJEMPLO 2



EJEMPLO 3




No hay comentarios:

Publicar un comentario

DELEGADOS EN C# .NET | PUNTEROS A METODOS

Delegados Tal como hemos comentado, los eventos y los delegados están muy unidos en C#. De hecho no se pueden definir eventos si no def...