Os explicamos cómo funciona el manejo de errores o excepciones en Visual Basci .Net, lenguaje de programación visual de Microsoft perteneciente a Visual Studio .Net. Os explicamos con ejemplos cómo capturar los posibles errores que se puedan producir en la ejecución normal del código para mostrar mensajes al usuario (o para que el usuario no se entere del error).

Manejo de errores en versiones anteriores de Visual Basic

En versiones anteriores de Visual Basic, como la versión 6, el control de errores se realizaba mediante:

o bien utilizando «On Error Resume Next».

Visual Basic .Net sigue permitiendo el uso de estas dos instrucciones para el control de errores, pero Microsoft recomienda encarecidamente que no se utilicen y se empleen las nuevas instrucciones Try…Catch…Finally.

El objeto Exception en Visual Basic .NET

El objeto Exception se encuentra definido en .NET Framework y su nombre completo es System.Exception. En este marco de trabajo se definen otras dos clases genéricas: System.SystemException y System.ApplicationException. Casi todos los objetos de Exception definidos en .NET Framework heredan de SystemException, mientras que los objetos de excepción personalizados y específicos de cada aplicación heredan de ApplicationException. Estas dos clases no agregan ninguna propiedad o método a la clase base Exception.

A continuación enumeramos algunas de las clases Exception en los espacios de nombres más importantes de .NET Framework:

Espacios de nombreClases de excepción
SystemArgumentNullException, ArgumentOutOfRangeException, DivideByZeroException, IndexOutOfRangeException, NullReference-Exception, OverflowException, StackOverflowException
System.IODirectoryNotFoundException, EndOfStreamException, FileNotFoundException, PathTooLongException, FileLoadException, DriveNotFoundException
System.DataDuplicateNameException, InvalidConstraintException, InvalidExpressionException, MissingPrimaryKeyException, NoNullAllowedException, ReadOnlyException
System.Runtime.InteropServicesInvalidComObjectException, InvalidOleVariantTypeException, SEHException

La instrucción Try…Catch…End Try ó Finally en Visual Basic .NET

La palabra clave Catch

Siempre que se añada código fuente que pueda iniciar una excepción será conveniente introducirlo en un bloque TryCatchEnd. El código que quede entre Try y Catch estará protegido contra excepciones y si se iniciara una excepción, Visual Basic pasaría el control al primer bloque Catch (filtro de excepciones). En el bloque de código Catch se podrán examinar las propiedades del objeto Exception y decidir cómo reaccionar al error.

Un ejemplo sencillo de control de excepciones:

En el ejemplo anterior se pide con un InputBox el valor de «y», se pueden dar varios casos según el valor introducido:

  • Si el valor de «y» es igual a cero se producirá un error (se iniciará una excepción), puesto que tenemos control de excepciones, en este caso no se ejecutará la línea de código y = CInt (10 ^ x), en su lugar se captura el error y Visual Basic pasará el control al bloque Catch, puesto que se ha introducido un cero en «y», se ejecutará la línea que hay a continuación de If ex.Message = «Intento de dividir por cero.» Then. Tras ejecutar este código saltará a la siguiente instrucción a la línea «End Try» (si la hay).
  • Si el valor de «y» es cualquier otro número distinto de cero no se producirá error por lo que se ejecutarán las líneas de código:
  • Si el valor de «y» es un número no entero (Integer) o una cadena de texto se producirá un error y el programa saltará al bloque Catch, en este caso se ejecutará la línea de código siguiente al «Else» del bloque Catch y se mostrará un mensaje de error como el siguiente:
El control de errores, manejo de errores, control de excepciones en Visual Basic .Net

La forma anterior no es la adecuada para tratar las excepciones, pues se está comprobando el contenido de la cadena Message, que contiene la descripción del mensaje de error que se haya producido. La forma adecuada es que existan varios bloques Catch, cada uno de los cuales comprobará un objeto Exception distinto, según el código que introduzcamos entre el Try y los Catch. Por ejemplo:

En el ejemplo anterior los posibles errores (excepciones) están correctamente capturados. Se pueden dar varios casos:

  • Si el valor de «y» es cero el programa saltará a los bloques Catch y, puesto que se producirá una excepción de tipo DivideByZeroException, se ejecutará el código que haya en el primer Catch.
  • Si el valor de «y» es un número muy grande el programa saltará a los bloques Catch y, puesto que se producirá una excepción de tipo OverflowException, se ejecutará el código que haya en el segundo Catch.
  • Si el valor de «y» es un texto (por ejemplo) el programa saltará a los bloques Catch y, puesto que se producirá una excepción de tipo diferente a DivideByZeroException y OverflowException, se ejecutará el código que haya en el tercer Catch.

Visual Basic comparará el tipo de objeto Exception que se haya iniciado con las expresiones contenidas en las cláusulas Catch en el orden en el que aparecen y ejecutará la primera que coincida. Es importante contar siempre con una expresión Catch final que coincida con el objeto System.Exception, como mostramos en el ejemplo anterior, porque este código siempre se ejecutará en el caso de que ninguna de las expresiones Catch anteriores coincidan con la excepción producida. Una cláusula Catch del objeto System.Exception siempre coincidirá con cualquier excepción porque todos los objetos Exception heredan de System.Exception.

Como todas las expresiones Catch se evalúan en el orden en que aparecen, es recomendable comprobar las excepciones más específicas en primer lugar, en el ejemplo en primer lugar hemos colocado DivideByZeroException. Como hemos dicho, la comprobación del objeto System.Exception deberá estar en el último bloque Catch porque coincidirá con cualquier excepcion. Por ello, ningún bloque Catch situado detrás de de esta comprobación se ejecutará jamás. Además, cuando se ordenen los bloques Catch, se deberá tener en cuenta la jerarquía de excepciones y comprobar que nunca va a intentar capturar un objeto Exception después de capturar a su excepción padre. Por ejemplo, el bloque Catch correspondiente al objeto DivideByZeroException nunca deberá encontrarse a continuación del objeto ArithmeticException que resulta menos específico.

Siempre se podrá salir de la estructura Try…End Try con la instrucción Exit Try, que puede insertarse dentro de un bloque Try o en cualquier bloque Catch.

La palabra clave When

Dentro de la cláusula Catch se podrá utilizar una expresión When opcional que le permitirá especificar una condición adicional que el bloque Catch deberá evaluar como True para que sea seleccionada. Esta característica permitirá definir filtros de excepciones más específicos.

La palabra clave Finally

En determinadas ocasiones es necesario ejecutar un código de limpieza cuando se produce una excepción. Por ejemplo para cerrar un fichero abierto en el caso en que se produzca un error, o para cerrar la conexión con una base de datos. En estos casos en los que queremos ejecutar. Usando la claúsula Finally, el código que coloquemos en ella siempre se ejecutará, tanto si se produce error como si no.