Control de Excepciones .NET
[
También se pueden lanzar excepciones propias, extendiendo la clase System.Exception]
( ¡¡¡...Hay que esperar lo inesperado !!! )

Fecha: 30/Abr/2005 (28/04/2005)
Autor: Arbis Percy Reyes Paredes - Perxindrome [email protected]

¡ los peruanos Sí podemos...!


mi decepción en la web...

Siempre que tengo tiempo "libre", me animo a explorar internet. Lo primero que hago es buscar lo que se me ocurra mediante google. Bueno el hecho es que busqué temas respecto a Control de Excepciones .NET  y no encontré mucho, la pocas publicaciones que habían hablaban de cosas supérfluas y muy conocidas, simplemente eras publicaciones muy corrientes, excepto los publicados por Microsoft, las demás no me ayudaron para nada. Lo que se necesita ahora es tener información a la mano y que sea de gran ayuda. Es así como me animé a realizar este artículo "Control de Excepciones .NET", con el único objetivo de ayudarte y explicarte al respecto. Mira, en primer lugar, este tema no es nada sencillo, muchos por "allí", pueden decir que Controlar excepciones es sencillo y lo puede hacer cualquiera. Pero es todo lo contrario, controlar y manejar excepciones es todo un reto, si es que se trabaja desarrollando grandes proyectos, de las cuales depende más que nuestra vida, depende nuestra continuación en nuestro centro de trabajo. Un simple descuido puede hacer que obvies algún caso que más tarde pueda originar un error y terminando por echarte abajo el software que estuvistes desarrollando por mucho tiempo. A los jefes no les importa tus justificaciones o explicaciones,cuando el software no funciona, ellos simplemente exigen y punto, y si no estas de acuerdo, entonces empaqueta tus cosas y a la calle. Es por eso que tienes que preucuparte mucho por hacer buenas prácticas con respecto a Control de Excepciones.

Este artículo no pretende darte una clase de maestría, o explicarte de una manera marciana este tema, sino más bien, explicarte cómo es que se origina una excepción y el porqué, presentándote para esto los procesos que se desencadenan debido al lanzamiento de una excepción. Pero lo que diferencia a este artículo de los demás, es que explico toda la filosofía de manejo de errores y cómo crear tus propias clases para manejar errores, es decir crear excepciones personalizadas.

...empecemos

Cuando me inicié en este mundo de desarrollo de software, siempre fue muy importante para mí controlar errores que pudieran surgir debido a muchas causas. Además todos sabemos que, en el mundo de la programación es común escuchar “hay que esperar lo inesperado”. Por ejemplo, considere el caso del ingreso de datos a un programa de inventarios a través de una interfaz, donde hay una caja de texto en la cual se ingresará el precio de una unidad de un producto determinado teniendo, para ello, la siguiente línea de código:

              Dim _precio As  Double   = Double.Parse(Me .TextPrecio.Text)

Se espera que todo vaya bien con la fuente de entrada que representa el objeto TextBox al cual se hace referencia mediante TextPrecio – invocando a la propiedad Text – y que, finalmente, dará lugar a una línea conteniendo un número. Lo inesperado no son únicamente problemas físicos, por ejemplo, que se intente grabar esta información a un archivo localizado en un disco duro que no funciona. Cuando se escribió esa línea de código se esperaba que apareciera un número en la caja de texto al llegar a este punto. Sin embargo, se pueden considerar las posibilidades siguientes:

Por supuesto esto no quiere decir que llegará el Papa negro o algo asi...simplemente el contexto en el cual se ejecuta el software no es tan predecible como se desearía que fuera. Los buenos programas están diseñados para tener esto en cuenta. Nosotros, los programadores profesionales tenemos que aprender a esperar lo inesperado. En caso de no controlar este error, al momento de llegar a este punto, aparecerá frente a nuestros ojos lo siguiente:

Excepción no controlada del tipo 'System.FormatException' en mscorlib.dll

 

1. Filosofia frente a lo inesperado

Responder a lo inesperado es una parte tan importante del comportamiento exigido para los objetos “útiles e inteligentes” como enfrentarse a lo esperado. Es sabido que el comportamiento se implementa con métodos. Ahora bien, ¿qué pueden hacer los métodos cuando se encuentran con lo inesperado?

Considere el método Double.Parse de la estructura Double. Su argumento es un String – si todo va bien, uno que sea una representación de un número de punto flotante de precisión doble. ¿Qué ocurre si no es así? ¿Qué debería hacer Double.Parse, por ejemplo, si su argumento es “PercyNet”?

Una de las cosas que no puede hacer Double.Parse es corregir el error – no tiene forma de conocer el valor que debería haber tenido el argumento. Además Double.Parse tampoco puede consultar al usuario para pedirle un valor correcto. En primer lugar, quizá no haya un usuario disponible. La invocación de Double.Parse puede encontrarse en un programa que esté procesando ficheros o llevando a cabo operaciones de red. En segundo lugar, es imposible hacer que Double.Parse haga saber al usuario el contexto en el cual se ha producido el problema, porque Double.Parse no sabe si está traduciendo un sueldo, un precio, el número de horas trabajadas, un número de alumnos o cualquier otra cosa. Puede haber centenares de lugares del programa en los cuales se lean enteros. De ser así, ¿cómo puede saber el usuario cuál es el valor correcto que debe escribir?

En suma, no es responsabilidad de Double.Parse corregir, ni siquiera identificar, el origen último del error. El argumento proviene de quien haya efectuado la llamada, así que la responsabilidad corresponde, por tanto, a quien haya llamado a Double.Parse. Consiguientemente, Double.Parse debe informar a quien haya efectuado la llamada de que se ha producido un problema. ¿Cómo se puede hacer esto?

Normalmente, la información procedente de un método se le comunica a quien lo invoca mediante un valor proporcionado. Es posible que se pudiera comunicar la existencia de una situación inesperada a través de un valor proporcionado que el que haya efectuado la llamada pudiera comprobar. Pero lo inesperado no sucede “normalmente”. Los desarrolladores de Microsoft que diseñaron Double.Parse no podían especificar que si el método se encontraba con un error se proporcionaría como resultado un String que fuera “formato numérico incorrecto” porque el prototipo de Double.Parse exige que siempre proporcione un número de punto flotante de precisión doble.

2. Lanzamiento de Exception

Los programas deben poder controlar los errores que se producen durante la ejecución de manera uniforme. Common Language Runtime ofrece una gran ayuda para diseñar software con tolerancia a errores mediante una plataforma que informa a los programas de los errores de manera uniforme. Todas las operaciones de .NET Framework informan de un error iniciando excepciones.

Hasta ahora, el modelo de control de errores de un lenguaje dependía de la forma exclusiva que tenía el lenguaje de detectar los errores y buscarles controladores o del mecanismo de control de errores proporcionado por el sistema operativo. El tiempo de ejecución implementa el control de excepciones con las características siguientes:

Las excepciones ofrecen varias ventajas respecto a otros métodos de notificación de error, como los códigos devueltos. Ningún error pasa desapercibido. Los valores no válidos no se siguen propagando por el sistema. No es necesario comprobar los códigos devueltos. Es muy sencillo agregar código de control de excepciones para aumentar la confiabilidad del programa.

Con objeto de permitir que los métodos respondan frente a circunstancias inesperadas, .net proporciona una forma alternativa de finalizar la ejecución del método. Esto se logra mediante la sentencia Throw (Inicia una excepción dentro de un procedimiento). Puede utilizar la instrucción Throw para interceptar errores dentro del código, porque Visual Basic asciende por la pila de llamadas hasta que encuentra el código de control de excepciones apropiado.  

Throw [referencia]

En donde la referencia corresponde a un objeto de alguna subclase de la clase Exception – una clase que representa situaciones inesperadas. La sentencia throw suele adoptar la forma siguiente:

                              Throw New Clase-de-Exception (argumento de tipo String)

En donde Clase-de-Exception es una subclase de Exception.

Un constructor de Exception admite como argumento un String que se imprimirá cuando se visualice la cadena de invocaciones. Esto permite que quien lance la Exception otorgue un rótulo a esa Exception con objeto de aportar información adicional.

Por ejemplo: En el siguiente código se utiliza la instrucción Throw para iniciar una excepción:

                            ' Throw  es una nueva excepción.
                                   Throw New System.Exception("Una excepción ha ocurrido.")

                     Esto sería el resultado:

 Throw New System.Exception(Una excepción ha ocurrido.)

Si eres curioso te darás cuenta que en la parte de Información adicional se encuentra nuestro mensaje que habiamos definido previamente más arriba.

Cuando un método ejecuta la sentencia Throw, se dice que lanza una excepción. Se puede considerar, por ejemplo, la cadena de invocaciones de métodos que da lugar a la invocación de un método particular. El primer método que se ejecuta es main. Éste invoca a un método que a su vez invoca a otro método y así sucesivamente hasta llegar al método que se encuentra con la situación inesperada.   

Si se produce una excepción en un método que no esté preparado para controlarla, la excepción se propagará de vuelta al método de llamada o al método anterior. Si el método anterior tampoco tiene controlador de excepciones, la excepción se propagará de vuelta al llamador del método, y así sucesivamente. La búsqueda de un controlador continuará hasta la pila de llamadas, que es la serie de procedimientos a los que se llama dentro de la aplicación. Si ésta tampoco encuentra un controlador para la excepción, se mostrará un mensaje de error y la aplicación finalizará. En la siguiente figura puede observarse todo el proceso de desencadenamiento en búsqueda de un controlador para administrar el error. 

La excepción asciende por la pila de invocaciones a cada bloque de excepciones que los
abarca.

El lanzamiento de una Exception da lugar a que el método que se está ejecutando finalice inmediatamente. Sin embargo, la sentencia throw no proporciona un valor, ni tampoco quien haya efectuado la llamada reanuda la ejecución desde el punto en que se ha producido la invocación. Lo que ocurre es que la Exception lanzada va pasando por todas las invocaciones habidas a lo largo de la cadena, obligando a que todos los métodos invocados vayan finalizando. Para todos los métodos que se encuentran en el camino, parece que el método fuera el que hubiera lanzado la Exception. De hecho, se puede decir que todos los métodos hallados a lo largo del camino lanzan la Exception. Finalmente, la cadena llegará al método main que ha hecho comenzar la ejecución, momento en el cual concluye el programa. Por tanto, la sentencia

 Throw [referencia-de-objeto-Exception]

...da lugar a que el programa concluya. Se puede pensar que se trata de una escotilla de escape. Sin embargo, la instrucción Throw inicia una excepción que se puede controlar con código de control estructurado de excepciones (Try...Catch...Finally) o con código de control no estructurado de excepciones (On Error GoTo).

3. Tipos de errores

En Visual Basic, los errores (también denominados excepciones) se dividen en tres categorías: errores sintácticos, errores en tiempo de ejecución y errores lógicos.

3.1 Errores sintácticos

Los errores sintácticos son aquellos que aparecen mientras se escribe el código. Visual Basic va comprobando el código a medida que se escribe y notifica los errores que detecta, como la escritura incorrecta de una palabra o el uso incorrecto de un elemento del lenguaje. Los errores sintácticos son los errores más frecuentes. Se pueden corregir fácilmente en el entorno de codificación en cuanto se producen.

Nota   La instrucción Option Explicit se utiliza para evitar que se produzcan errores sintácticos, ya que obliga al programador a declarar, por anticipado, todas las variables que se vayan a utilizar en la aplicación. De este modo, cuando se utilicen las variables en el código, cualquier error tipográfico que se produzca se capturará de forma inmediata, y podrá corregirse.

3.2 Errores en tiempo de ejecución

Los errores en tiempo de ejecución son aquellos que aparecen solamente después de la compilación y la ejecución del código. Pueden darse errores de este tipo, por ejemplo, en fragmentos de código aparentemente correctos, por no presentar errores sintácticos, pero que no se ejecutan correctamente. Por ejemplo, podría escribir correctamente una línea de código que abre un archivo. Pero, si el archivo está dañado, la aplicación no podrá ejecutar la función Open, y se detendrá su ejecución. La mayoría de los errores de este tipo pueden corregirse modificando el código que presenta errores, para después compilarlo y volver a ejecutarlo.

3.3 Errores lógicos

Los errores lógicos son aquellos que aparecen cuando la aplicación está en funcionamiento. Normalmente se manifiestan en forma de resultados inesperados o no deseados en respuesta a las acciones del usuario. Por ejemplo, una clave mal escrita u otra influencia externa podría hacer que la aplicación dejase de funcionar aún siendo correctos los parámetros, o que simplemente no funcionase. Por lo general, los errores lógicos son los más difíciles de corregir, puesto que no siempre está claro dónde se originan.

4. Manejo de lo inesperado

4.1. Manejo estructurado de excepciones

Las excepciones son conceptos del sistema con un enfoque estructurado, el cual es implementado por el Motor de ejecución común de los lenguajes .NET, es posible atrapar una excepción en un nivel externo de la ejecución. Incluso es posible tener excepciones anidadas: si un manejador de errores por si mismo lanza una excepción, también puede ser atrapada y todavía se puede examinar la razón del error original.

Forma sintáctica de manejo: Un manejo de excepción se implementa utilizando la instrucción de bloque Try…Catch…Finally.

El motor de ejecución empieza a ejecutar el bloque Try. Cuando se lanza una excepción, el motor de ejecución examina la pila de llamadas, una lista de las llamadas de función creadas por el programa que se está ejecutando actualmente. Esta ruta de ejecución puede tener varias funciones. Por ejemplo, si Main() invoca FirstMethod() y ese método invoca SecondMethod() y ese método invoca ThirdMethod(), todos éstos están en la pila de invocaciones.

La excepción asciende por la pila de invocaciones a cada bloque de excepciones que los abarca. Debido a que la pila no es modificada, cada bloque de excepción recibe la oportunidad de manejar la excepción. Si la excepción puede ser resuelta por una de las instrucciones Catch, ejecuta la instrucción de manejo. Si la excepción no concuerda con ninguna de las instrucciones Catch en el bloque de excepción, la pila está nuevamente sin modificación y la excepción se presenta al siguiente método. Si la excepción recorre todo el camino hacia el inicio del programa (por ejemplo, a Main()) y no ha sido manejada, el motor de ejecución muestra un cuadro de diálogo que declara que ha ocurrido una excepción no manejada.

Observe que el desenrollado de pila sólo va en una dirección. Debido a que la pila no está dañada, se destruyen los objetos. Una vez que se maneja la excepción, el programa continúa después del bloque Try de la instrucción Catch que manejó la excepción. Si el bloque Try ha sido ejecutado sin haber lanzado una excepción, o un bloque Catch (un manejador de excepciones) ha sido ejecutado, se ejecuta el bloque Finally correspondiente al bloque Try o Catch que acaba de terminar. Este bloque normalmente se limpia después del algoritmo. (ver figura anterior)

Nota: Todo referente tan sólo a Control no estructurado de excepciones fue tomado de la ayuda de Microsoft, pero no me limito a esto, al final agrego un ejemplo 02, la cual ilustra mejor la práctica de control no estructurado de excepciones.

Por omisión la sentencia Throw desencadena una colección de finalizaciones de métodos, comenzando por el método que ejecuta la sentencia Throw y acabando en el método main del programa, dando lugar a la conclusión del programa en sí. Esto suele ser una forma excesivamente brutal de tratar una situación inesperada. Suele ser posible que el programa responda a lo inesperado y se recupere.

 ¿Cómo puede un método responder a una Exception lanzada por otro método que haya invocado? .net proporciona una forma en que los métodos pueden capturar cualquier Exception que les llegue, habiendo sido lanzada por algún método que hayan invocado. La captura de una Exception significa romper la cascada de lanzamiento de Exception que da lugar a la terminación del programa. En este caso, el método que captura la Exception recupera el control y entonces puede – se espera – manejar la situación de una forma menos extrema que una abrupta terminación del programa.

 Para capturar una Exception, las sentencias que contengan invocaciones de métodos que lancen Exceptions tienen que ir encerradas (para vb .net, por ejemplo) entre las palabras reservadas Try ... Catch:

Try

      AlgunObjetoNet.AlgunMetodoNet()

Catch ex As Exception

     ....

                                 End Try

A continuación, de la palabra reservada Catch debe ir una declaración de una variable referencia que hará alusión al objeto Exception lanzado. Esto en el código anterior sería:

                                                  ... Catch ex As Exception   ....

Después de esto viene una colección de sentencias encerradas entre llaves. Si se lanza una excepción, entonces se ejecutarán  esas sentencias cuando el objeto Exception alcance este método:

Try

     AlgunObjetoNet.AlgunMetodoNet()

Catch ex As Exception

      [sentencias que se ejecutan si y sólo si el código

      contenido en el bloque Try lanza una excepción]

End Try

El código que aparece entre las llaves que siguen a la palabra reservada  Try es lo que se denomina el bloque Try; también diremos que este código está rodeado por un Try...Catch. El código que aparece después del match es lo que examina el bloque catch.

Pueden declararse varias referencias a objetos Exceptions:

Dim MyDate As Object 'Debe contener un date/time
Dim MyNextDate As Date 'para almacenar el año; truncado al valor integral.
Try
    MyNextDate = DateAdd("yyyy", 100, MyDate)
Catch ThisExcep As System.ArgumentException
   
    ' El argumento proporcionado para el método no es válido.
Catch ThisExcep As ArgumentOutOfRangeException
   
    'el valor del argumento se encuentra fuera del intervalo de valores 
   
    'permitido definido por el método invocado.Esta excepción se dará 
   
    'cuando el resultado está después del 31 Diciembre de 9999.
Catch ThisExcep As InvalidCastException
   
    'La fecha obtenida no puede ser convertida a date/time.
End Try

El paso final en la captura de una excepción es proporcionar un mecanismo que limpie el estado del método antes (posiblemente) de permitir que el control pase a otra parte diferente del programa. Se puede hacer esto encerrando el código de limpieza dentro de un bloque F inally

Dim MyDate As Object 'Debe contener un date/time
Dim MyNextDate As Date 'para almacenar el año; truncado al valor integral.
Try
    MyNextDate = DateAdd("yyyy", 100, MyDate)
Catch ThisExcep As System.ArgumentException
   
    ' El argumento proporcionado para el método no es válido.
Catch ThisExcep As ArgumentOutOfRangeException
   
    'el valor del argumento se encuentra fuera del intervalo de valores 
   
    'permitido definido por el método invocado.Esta excepción se dará 
   
    'cuando el resultado está después del 31 Diciembre de 9999.
Catch ThisExcep As InvalidCastException
   
    'La fecha obtenida no puede ser convertida a date/time.
Finally
   
    'sentencias que se ejecutan independientemente si ocurrió o no el lanzamiento de la excepción.

End Try

El sistema de ejecución siempre ejecuta las sentencias que hay  dentro del bloque Finally sin importar lo que suceda dentro del bloque Try.

4.1.1. Lanzar excepciones propias

También se pueden lanzar excepciones propias, extendiendo la clase System.Exception. Por ejemplo:

'Construímos nuestra propia clase Exception para lanzar excepciones.
Public Class MiExcepcion
    Inherits System.Exception
    Sub New()
    End Sub
    'aplicando conceptos de polimorfismo...
    Public Overrides Function ToString() As String
        Return "Error:'Division entre cero no es posible'"
    End Function
End Class

Public Function divide(ByVal x As Integer, ByVal y As Integer) As Integer
    Dim z As Integer
    Try
        z = x / y

   Catch ex As System.ArithmeticException
        z = -1        

  Throw New MiExcepcion 'lanzamos la excepción.
        Return z
    End Try
End Function

Private Sub BtnCalcular_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnCalcular.Click

    Dim x, y As Double
     Dim r As Double = 0

     Try
         x = Double.Parse(Me.TextDividendo.Text)
         y = Double.Parse(Me.TextDivisor.Text)

     Catch ex As Exception

          MsgBox("Ingrese números")
          Me.TextDividendo.Clear()
          Me.TextDivisor.Clear()
           Me.TextResultado.Text = "Operación sin éxito"
          Return
     End Try

   Try
        r = divide(x, y)

    C atch ex As MiExcepcion 'capturamos la excepción que habíamos lanzado.

         Me.TextResultado.Text = ex.ToString()
       r = -1

   End Try

   If (r <> -1) Then
       Dim z As Double = CType(x / y, Double)
       Me.TextResultado.Text = z
   End If

  End Sub

          Estos son los resultados. Si ingreso un número y una cadena String, desde luego que debe desencadenarse una excepción.

Lanzar excepciones propias

....también debe originarse una excepción, al intentar dividir entre cero. Recuerda que esta excepción la estamos manejando mediante  la clase que habíamos extendido de la clase System.Exception.

 

lanzar excepciones propias

 Por muchas razones podemos obviar u olvidarnos de manejar o controlar ciertas excepciones fatales durante el desarrollo de un proyecto, aplicación o yo que sé lo que estés desarrollando. Hago este comentario debido a que existe maneras de controlar de manera genérica todos estas excepciones "inesperadas". Inserta este código en la parte inicial de tu aplicación...y te habrás evitado de grandes sustos.

Public Class Form1
Inherits System.Windows.Forms.Form
 
'[aquí va el Código generado por le diseñador de Windows Form]
 
Public Shared Sub main() 'implementando un Controlador genérico de excepciones...
Try Application.Run(New Form1) 'Form1 viene a ser el nombre de nuestro formulario.
 Catch ex As Exception MsgBox(ex.InnerException.ToString)
 End Try
End Sub
 
'.....[demás eventos, procedimientos y funciones...]
End Class

        4.2. Control no estructurado de excepciones

En el caso del control no estructurado de excepciones, se coloca una instrucción On Error al principio de un bloque de código, En el caso del control no estructurado de excepciones, se coloca una instrucción On Error al principio de un bloque de código, que controla todos los errores que se producen dentro del bloque. Cuando se genera una excepción en un procedimiento después de que se haya ejecutado la instrucción On Error, el programa salta al argumento line especificado en la instrucción On Error. El argumento line, que es cualquier etiqueta de línea o número de línea, indica la ubicación del controlador de excepción

A veces se efectúa una llamada desde el procedimiento original hasta otro procedimiento, y se produce una excepción en el procedimiento al que se llama. En estos casos, si el procedimiento al que se llama no controla la excepción, ésta se propaga de vuelta al procedimiento que realiza la llamada y la ejecución salta al argumento line.

Nota   El método de control de errores no estructurado por medio de On Error puede degradar el rendimiento de la aplicación y puede dificultar la depuración y el mantenimiento del código. Se recomienda utilizar el método de control de errores estructurado.

On Error GoTo Line

La instrucción On Error GoTo Line presupone que el código de control de errores comienza en la línea especificada en el argumento line requerido. Si se produce un error en tiempo de ejecución, el control se transfiere a la etiqueta o al número de línea especificado en el argumento, con lo que se activa el controlador de errores. La línea especificada debe estar en el mismo procedimiento que la instrucción On Error GoTo Line; de lo contrario, Visual Basic generará un error de compilación. En el siguiente ejemplo se muestra el uso de un controlador de errores con una etiqueta de línea:

Sub TestSub
 
        On Error GoTo ErrorHandler
    
           ' Code that may or may not contain errors.
 
        Exit Sub
   ErrorHandler:
     
      ' Code that handles errors.
     
      Resume
End Sub

El ejemplo contiene un controlador de errores denominado ErrorHandler. Si el código de la subrutina TestSub genera un error, Visual Basic ejecuta de forma inmediata el código que sigue a la etiqueta ErrorHandler. Al final del bloque de control de errores, la instrucción Resume transfiere el control de nuevo a la línea de código en la que se produjo el error por primera vez. Después continúa la ejecución del resto de la subrutina como si no se hubiese producido ningún error.

Nota   Debe colocar una instrucción Exit Sub inmediatamente antes de bloque de control de errores. De lo contrario, Visual Basic ejecutará el código de control de errores cuando llegue al final de la subrutina, lo que puede provocar resultados inesperados o no deseados.

On Error Resume Next

La instrucción On Error Resume Next especifica que, en caso de que se produzca un error en tiempo de ejecución, el control pase a la instrucción inmediatamente siguiente a aquélla en que se haya producido el error. La ejecución continúa en ese punto. On Error Resume Next permite colocar las rutinas de control de errores en los lugares donde se prevea que pueden producirse, en lugar de transferir el control a otro punto del procedimiento.

Nota   Si un procedimiento llama a otro procedimiento, la instrucción On Error Resume Next permanece inactiva durante la ejecución del procedimiento al que se ha llamado. Por lo tanto, debe colocar una instrucción On Error Resume Next en cada procedimiento al que se llame que la necesite. Esto es necesario porque el comportamiento de Resume Next sólo se aplica al procedimiento que contiene la instrucción On Error Resume Next. Si se produce un error no controlado en un procedimiento al que se ha llamado, la excepción se propaga de vuelta al procedimiento que realizó la llamada, y la ejecución se reanuda en la instrucción siguiente a la del procedimiento de llamada. Es estos casos, no se controla el error.

Resume también puede utilizarse de forma independiente, fuera de la instrucción On Error. Si se utiliza Resume de esta forma, Visual Basic devuelve el control a la instrucción que provocó el error. Resume suele utilizarse después de que un controlador de errores corrija el error.

Visual Basic dispone también de la instrucción Resume Next, que dirige el control a la línea inmediatamente posterior a la línea de código que ha provocado el error. Debería utilizar Resume Next en aquellos casos en los que un error no detenga la ejecución de la aplicación. También debería utilizarla si un error dado no cambia el resultado esperado de la subrutina.

Otra variación de la instrucción Resume es Resume Line, que es similar a On Error GoTo Line. Resume Line pasa el control a la línea que se especifique en el argumento line. Resume Line sólo puede utilizarse dentro de un controlador de errores.

Nota   A la hora de depurar el código, debe deshabilitar la instrucción On Error Resume Next.

On Error GoTo 0

La instrucción On Error GoTo 0 deshabilita cualquier control de errores del procedimiento actual. Si no incluye una instrucción On Error GoTo 0, el controlador de errores se deshabilita igualmente cuando finaliza el procedimiento que contiene el controlador de excepción.

Nota   La instrucción On Error GoTo 0 no pretende especificar la línea 0 como el inicio del código de control de errores, aunque el procedimiento contenga una línea con el número 0.

On Error GoTo -1

La instrucción On Error GoTo -1 deshabilita todos los controladores de excepciones del procedimiento actual. Si no incluye una instrucción On Error GoTo -1, la excepción se deshabilita automáticamente cuando finaliza el procedimiento.

Nota   La instrucción On Error GoTo -1 no pretende especificar la línea -1 como el inicio del código de control de errores, aunque el procedimiento contenga una línea con el número -1.

4.2.1. Ejemplos de control no estructurado de excepciones

Ejemplo 01

En el código que se muestra a continuación, el controlador de excepciones se denomina DivideByZero y controla un error específico, el de intentar dividir un número por cero. Si el error es otro, Visual Basic genera un error en tiempo de ejecución y detiene la aplicación.

Sub ErrorTest()
   
    ' Declare variables.
   
    Dim x As Integer, y As Integer, z As Integer
   
    ' The exception handler is named "DivideByZero".
   
    On Error GoTo DivideByZero
   
    ' The main part of the code, which might cause an error.
    x = 2
    y = 0
    z = x \ y
   
    ' This line disables the exception handler.
   
    On Error GoTo 0
    Console.WriteLine(x & "/" & y & " = " & z)
   
    ' Exit the subroutine before the error-handling code.
   
    ' Failure to do so can create unexpected results.
   
    Exit Sub
   
    ' This is the exception handler, which deals with the error.
   
    DivideByZero:
   
    ' Include a friendly message to let the user know what is happening.
   
    Console.WriteLine("You have attempted to divide by zero!")
   
    ' Provide a solution to the error.
    y = 2
   
    ' The Resume statement returns to the point at which
   
    ' the error first occurred, so the application
   
    ' can continue to run.
   
    Resume

End Sub
Ejemplo 02

En el código que se muestra a continuación, el controlador de excepciones se denomina MyException y ya no controla un error específico, sino varios errores, como por ejemplo, el de intentar ingresar datos de tipo cadena y luego de ingresar un número, controla de que este sea tipo Byte, es decir el ingreso correcto debe ser un número de tipo Byte [entre 0 y 255]. Si el error es otro, Visual Basic genera un error en tiempo de ejecución y muestra el número que identifica al error.

Public Class Form1
   
    Inherits System.Windows.Forms.Form
   
    '[aquí va  el Código generado por le diseñador de Windows Form]
   
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
       
        Dim n As Byte
       
        On Error GoTo MyException
        n = CType(Me.TextBox1.Text, Byte)
        MsgBox("Usted escribió " & n.ToString, MsgBoxStyle.Information, "Ingreso de datos correctos" )
       
        Exit Sub
       
        MyException:
       
        Select Case Err.Number
           
            Case 6 : MsgBox("Escriba un número entre 0 y 255", MsgBoxStyle.Exclamation, "On Error GoTo")
           
            Case 13 : MsgBox("Sólo se admiten números", MsgBoxStyle.Exclamation, "On Error GoTo")
           
            Case Else
                MsgBox(Err.Description & ": " & Err.Number.ToString, MsgBoxStyle.Exclamation, "On Error GoTo")
       
        End Select
Me.TextBox2.Text = "Err.LastDllError: " + Err.LastDllError.ToString + _
                           vbCrLf + "err.Source: " + Err.Source + _
                           vbCrLf + "err.Number: " + Err.Number.ToString + _
                           vbCrLf + "err.HelpFile: " + Err.HelpFile.ToString + _
                          vbCrLf + "err.HelpContext: " + Err.HelpContext.ToString + _
                          vbCrLf + "Err.Description: " + Err.Description.ToString
     End Sub

La excepción asciende por la pila de invocaciones a cada bloque de excepciones que los
abarca.
5. Jerarquía de excepciones del motor de tiempo de ejecución

El motor de tiempo de ejecución tiene un conjunto base de excepciones que derivan de SystemException, que inicia cuando está ejecutando instrucciones individuales. En la tabla siguiente se muestran jerárquicamente las excepciones estándar que proporciona el motor de tiempo de ejecución y las condiciones en que se debe crear una clase derivada. Los nombres de las excepciones indican la condición de error que representan. Las siguientes son las excepciones predefinidas más frecuentes que se pueden encontrar:

Tipo de excepciónTipo baseDescripciónEjemplo
ExceptionObjectClase base de todas las excepciones.Ninguno (utilice una clase derivada de esta excepción).
SystemExceptionExceptionClase base de todos los errores que genera el motor de tiempo de ejecución.Ninguno (utilice una clase derivada de esta excepción).
IndexOutOfRangeExceptionSystemExceptionLa inicia el motor de tiempo de ejecución sólo cuando no se indiza correctamente una matriz.Indización de una matriz fuera de su intervalo válido:

arr[arr.Length+1]

NullReferenceExceptionSystemExceptionLa inicia el motor de tiempo de ejecución sólo cuando se hace referencia a un objeto nulo. object o = null;

o.ToString();

InvalidOperationExceptionSystemExceptionLa inician los métodos que se encuentran en un estado no válido.Llamar a Enumerator.GetNext() después de eliminar un Item de la colección subyacente.
ArgumentExceptionSystemExceptionClase base de todas las excepciones de argumento.Ninguno (utilice una clase derivada de esta excepción).
ArgumentNullExceptionArgumentExceptionLa inician los métodos que no permiten que un argumento sea nulo.String s = null;

"Calculate".IndexOf (s);

ArgumentOutOfRangeExceptionArgumentExceptionLa inician los métodos que comprueban que los argumentos están en un intervalo dado.String s = "string";

s.Chars[9];

ExternalExceptionSystemExceptionClase base de las excepciones que se producen a o van dirigidas a entornos fuera del motor de tiempo de ejecución.Ninguno (utilice una clase derivada de esta excepción).
ComExceptionExternalExceptionExcepción que encapsula información de HRESULT de COM.Se usa en la interoperabilidad COM.
SEHExceptionExternalExceptionExcepción que encapsula información de control de excepciones estructurada de Win32.Se usa en la interoperabilidad de código no administrado.

Hemos llegado a la parte final. Quiero darte las gracias por haberte molestado en leer este artículo, pero yo me molestaré más si tú no  pones en práctica lo aprendido el día de hoy, recuerda lo que no se practica se olvida. No me quejo de nada, sólo quiero decirles a todos ustedes amigos desarrolladores, que todo esto lo realicé pensando en colaborar y ser de utilidad al mundo. Espero que les sea de utilidad la idea que aporté, si encuentras algunos errores o si tienes algunas ideas que puedan servirme para mejorar mis próximas publicaciones, no dudes en escribirme al correo, ya que tú serás el que salga beneficiado al final de todo. Ya es demasiado tarde, creo que también debo dormir, mis párpados no aguantan, pero  despertaré con muchas ganas para editar otro artículo para tí. Nos Vemos.

No olvides de darme tu voto en PanoramaBox, ya que es una manera de animarme a seguir compartiendo contigo lo que voy aprendiendo. Gracias


Espacios de nombres usados en el código de este artículo:

System.Exception

System.ApplicationException

System.SystemException


ir al índice