Instrucción Try...Catch...Finally (Visual Basic)
Esta instrucción proporciona una manera de controlar algunos o todos los errores posibles que pueden ocurrir en un bloque de código determinado mientras se ejecuta el código.
Try
[ tryStatements ]
[ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ]
[ Exit Try ] ]
[ Catch ... ]
[ Finally
[ finallyStatements ] ]
End Try
Elementos
Término |
Definición |
tryStatements |
Opcional.Instrucciones en las que puede ocurrir un error.Puede ser una instrucción compuesta. |
Catch |
Opcional.Se permite utilizar varios bloques Catch.Si se produce una excepción al procesar el bloque Try, cada instrucción Catch se examina en orden textual para determinar si controla la excepción; el parámetro exception representa la excepción que se ha producido. |
exception |
Opcional.Cualquier nombre de variable.El valor inicial de exception es el valor del error producido.Se utiliza con Catch para especificar la captura del error.Si se omite, la instrucción Catch detecta cualquier excepción. |
type |
Opcional.Especifica el tipo de filtro de clase.Si el valor de exception es del tipo especificado en type o de un tipo derivado, el identificador queda enlazado al objeto de excepción. |
When |
Opcional.Una instrucción Catch con una cláusula When sólo detecta las excepciones cuando expression se evalúa como True.Una cláusula When sólo se aplica después de comprobar el tipo de la excepción y expression puede hacer referencia al identificador que representa la excepción. |
expression |
Opcional.Debe ser convertible implícitamente a Boolean.Cualquier expresión que describe un filtro genérico.Se utiliza normalmente para filtrar por número de error.Se utiliza con la palabra clave When para especificar las circunstancias bajo las que se captura el error. |
catchStatements |
Opcional.Instrucciones para controlar los errores que se producen en el bloque Try asociado.Puede ser una instrucción compuesta. |
Exit Try |
Opcional.Palabra clave que interrumpe la ejecución de la estructura Try...Catch...Finally.La ejecución se reanuda con el código que sigue inmediatamente a la instrucción End Try.Se ejecutará la instrucción Finally todavía.No se permite en bloques Finally. |
Finally |
Opcional.Siempre se ejecuta un bloque Finally cuando la ejecución sale de cualquier parte de la instrucción Try...Catch. |
finallyStatements |
Opcional.Instrucciones que se ejecutan después de las demás operaciones de procesamiento de error. |
End Try |
Finaliza la estructura Try...Catch...Finally. |
Comentarios
Si piensa que se puede producir una excepción determinada en una sección concreta del código, incluya éste en un bloque Try y utilice un bloque Catch para conservar el control y tratar la excepción que se produce.
Una instrucción Try…Catch consiste en un bloque Try seguido de una o más cláusulas Catch, que especifican controladores para varias excepciones.Cuando se produce una excepción en un bloque Try, Visual Basic busca la instrucción Catch que controla la excepción.Si no se encuentra una instrucción Catch coincidente, Visual Basic examina el método que llamó al método actual, y así sucesivamente hasta la pila de llamadas.Si no se encuentra ningún bloque Catch, Visual Basic muestra al usuario un mensaje de excepción no controlada y detiene la ejecución del programa.
Puede utilizar más de una instrucción Catch en una instrucción Try…Catch .Si lo hace, el orden de las cláusulas Catch es significativo debido a que se examinan en orden.Las excepciones más específicas se capturan antes que las menos específicas.
Las siguientes condiciones de la instrucción Catch son las menos específicas y detectarán todas las excepciones que se deriven de la clase Exception.Normalmente debe utilizar una de estas variaciones como el último bloque Catch de la estructura Try...Catch...Finally, después de detectar todas las excepciones específicas que espera.El flujo de control nunca puede alcanzar un bloque Catch situado detrás de cualquiera de estas variaciones.
El type es Exception, por ejemplo: Catch ex As Exception
La instrucción no tiene ninguna variable exception, por ejemplo: Catch
Cuando una instrucción Try…Catch…Finally está anidada en otro bloque Try, Visual Basic primero examina cada instrucción Catch en el bloque Try más interno.Si no encuentra ninguna instrucción Catch coincidente, la búsqueda continúa en las instrucciones Catch del bloque Try…Catch…Finally exterior.
Las variables locales de un bloque Try no se encuentran disponibles en un bloque Catch porque se trata de bloques independientes.Si se desea utilizar una variable en más de un bloque, se debe declarar la variable fuera de la estructura Try...Catch...Finally.
Sugerencia |
---|
La instrucción Try…Catch…Finally está disponible como un fragmento de código de IntelliSense.En el Administrador de fragmentos de código, expanda Modelos de código - If, For Each, Try Catch, Property, etc, y Control de errores (excepciones).Para obtener más información, vea Fragmentos de código. |
Bloque Finally
Si tiene una o más instrucciones que se deben ejecutar antes de salir de la estructura Try, utilice un bloque Finally.El control pasa al bloque Finally justo antes de salir de la estructura Try…Catch.Esto se produce incluso si aparece una excepción dentro de la estructura Try.
Un bloque Finally es útil para ejecutar cualquier código que debe ejecutar incluso si hay una excepción.El control se pasa al bloque Finally independientemente de cómo se sale del bloque Try...Catch.
El código de un bloque Finally se ejecuta incluso si el código encuentra una instrucción Return en un bloque Try o Catch.El control no pasa de un bloque Try o Catch al bloque Finally correspondiente en los casos siguientes:
Se encuentra End (Instrucción) en el bloque Try o Catch.
Se produce StackOverflowException en el bloque Try o Catch.
No es válido explícitamente transferir la ejecución en un bloque de Finally .Transferir la ejecución de un bloque de Finally no es válido, pero con una excepción.
Si una instrucción Try no contiene al menos un bloque Catch, debe contener un bloque Finally.
Sugerencia |
---|
Si no tiene que detectar excepciones específicas, la instrucción Using se comporta como un bloque Try…Finally y garantiza la disposición de los recursos, independientemente de cómo salga del bloque.Esto es cierto incluso con una excepción no controlada.Para obtener más información, vea Using (Instrucción, Visual Basic). |
Argumento de la excepción
El argumento exception del bloque Catch es una instancia de la clase Exception o una clase que se deriva de la clase Exception.La instancia de la clase Exception corresponde al error que se produjo en el bloque Try.
Las propiedades del objeto Exception ayudan a identificar la causa y la ubicación de una excepción.Por ejemplo, la propiedad StackTrace muestra una lista de los métodos llamados que generaron la excepción, lo que ayuda a detectar el lugar del código en el que ocurrió el error.Message devuelve un mensaje que describe la excepción.HelpLink devuelve un vínculo a un archivo de ayuda asociado.InnerException devuelve el objeto Exception que causó la excepción actual, o devuelve Nothing si no hay ninguna Exception original.
Consideraciones sobre cuándo utilizar una instrucción Try…Catch
Utilice una instrucción Try…Catch solo para indicar la ocurrencia de eventos de programa inusuales o imprevistos.Esto pasa por las siguientes razones:
Detectar excepciones en tiempo de ejecución crea sobrecarga adicional, y es probable que sea más lento que la comprobación previa para evitar excepciones.
Si un bloque Catch no se maneja correctamente, puede que no se informe correctamente a los usuarios acerca de la excepción.
El control de excepciones hace a un programa más complejo.
No siempre es necesario una instrucción Try…Catch para comprobar una condición que es probable que ocurra.El siguiente ejemplo comprueba si existe un archivo antes de intentar abrirlo.Esto reduce la necesidad de detectar una excepción iniciada por el método OpenText .
Private Sub TextFileExample(ByVal filePath As String)
' Verify that the file exists.
If System.IO.File.Exists(filePath) = False Then
Console.Write("File Not Found: " & filePath)
Else
' Open the text file and display its contents.
Dim sr As System.IO.StreamReader =
System.IO.File.OpenText(filePath)
Console.Write(sr.ReadToEnd)
sr.Close()
End If
End Sub
Asegúrese de que el código de los bloques Catch puede informar correctamente de las excepciones a los usuarios, ya sea a través del registro seguro para subprocesos o de mensajes adecuados.De lo contrario, las excepciones podrían seguir siendo desconocidas.
Métodos Async
Si marca un método con el modificador de Asincrónica , puede utilizar el operador de Espera en el método.Un fragmento con el operador de Await suspende la ejecución del método hasta que la tarea aguardada complete.La tarea representa el trabajo en curso.Cuando la tarea asociada a los finals de operador de Await , ejecución se reanuda en el mismo método.Para obtener más información, vea Flujo de control en programas asincrónicos (C# y Visual Basic).
Una tarea devuelta por un método Async puede finalizar con errores, indicando que completó debido a una excepción no controlada.Una tarea también puede finalizar en un estado cancelado, que da lugar a OperationCanceledException que se va a iniciar de la expresión de aguardar.Para detectar cualquier tipo de excepción, coloque la expresión de Await asociado a la tarea en un bloque de Try , y detectar la excepción en el bloque de Catch .Un ejemplo se explica más adelante en este tema.
Una tarea puede estar con errores porque varias excepciones son responsables del error.Por ejemplo, la tarea puede ser el resultado de una llamada a Task.WhenAll.Cuando se espera por tarea, la excepción detectada es solo una de las excepciones, y no puede predecir qué excepción se detectar.Un ejemplo se explica más adelante en este tema.
Una expresión de Await no puede estar dentro de un bloque de Catch o de bloque de Finally .
Iteradores
Una función de iterador o un descriptor de acceso de Get realiza una iteración personalizada en una colección.Un iterador utiliza un fragmento de producción para devolver cada elemento de la colección de uno en uno.Llama a una función de iterador mediante Instrucción For Each...Next (Visual Basic).
Un fragmento de Yield puede estar dentro de un bloque de Try .Try bloqueos que contiene un fragmento de Yield puede tener bloques de Catch , y un bloque de Finally .Vea “bloque Try en la sección de Visual Basic” de Iteradores (C# y Visual Basic) para obtener un ejemplo.
Un fragmento de Yield no puede estar dentro de un bloque de Catch o bloque de Finally .
Si el cuerpo de For Each (fuera de la función de iterador) produce una excepción, un bloque de Catch en la función de iterador no se ejecuta, pero un bloque de Finally en la función de iterador se ejecuta.Un bloque de Catch dentro de una función de iterador detecta las excepciones que se producen dentro de la función de iterador.
Situaciones de confianza parcial
En situaciones de confianza parcial, como una aplicación hospedada en un recurso compartido de red, Try...Catch...Finally no detectará las excepciones de seguridad que se produzcan antes de llamar al método que contiene la llamada.El ejemplo siguiente, si se coloca en un recurso compartido de servidor y se ejecuta desde el mismo, producirá el error: "Sub System.Security.SecurityException: Error de solicitud". Para obtener más información sobre excepciones de seguridad, vea la clase SecurityException.
Try
Process.Start("https://www.microsoft.com")
Catch ex As Exception
MsgBox("Can't load Web page" & vbCrLf & ex.Message)
End Try
En este tipo de situación de confianza parcial, debe colocar la instrucción Process.Start en un procedimiento Sub independiente.La llamada inicial a Sub producirá un error.Esto permite que Try...Catch lo capture antes de que se inicie el procedimiento Sub que contiene Process.Start y se produzca la excepción de seguridad.
Ejemplo
El ejemplo siguiente muestra la estructura de la instrucción Try...Catch...Finally.
Public Sub TryExample()
' Declare variables.
Dim x As Integer = 5
Dim y As Integer = 0
' Set up structured error handling.
Try
' Cause a "Divide by Zero" exception.
x = x \ y
' This statement does not execute because program
' control passes to the Catch block when the
' exception occurs.
MessageBox.Show("end of Try block")
Catch ex As Exception
' Show the exception's message.
MessageBox.Show(ex.Message)
' Show the stack trace, which is a list of methods
' that are currently executing.
MessageBox.Show("Stack Trace: " & vbCrLf & ex.StackTrace)
Finally
' This line executes whether or not the exception occurs.
MessageBox.Show("in Finally block")
End Try
End Sub
En el ejemplo siguiente, el método CreateException arroja una NullReferenceException.El código que genera la excepción no está en un bloque Try .Por lo tanto, el método CreateException no controla la excepción.El método RunSample no controla la excepción porque la llamada al método CreateException está en un bloque Try.
El ejemplo incluye instrucciones Catch para varios tipos de excepciones, ordenadas de la más específica a la más general.
Public Sub RunSample()
Try
CreateException()
Catch ex As System.IO.IOException
' Code that reacts to IOException.
Catch ex As NullReferenceException
MessageBox.Show("NullReferenceException: " & ex.Message)
MessageBox.Show("Stack Trace: " & vbCrLf & ex.StackTrace)
Catch ex As Exception
' Code that reacts to any other exception.
End Try
End Sub
Private Sub CreateException()
' This code throws a NullReferenceException.
Dim obj = Nothing
Dim prop = obj.Name
' This code also throws a NullReferenceException.
'Throw New NullReferenceException("Something happened.")
End Sub
En el ejemplo siguiente se muestra cómo utilizar una instrucción Catch When para filtrar una expresión condicional.Si la expresión condicional se evalúa a True, se ejecuta el código en el bloque Catch.
Private Sub WhenExample()
Dim i As Integer = 5
Try
Throw New ArgumentException()
Catch e As OverflowException When i = 5
Console.WriteLine("First handler")
Catch e As ArgumentException When i = 4
Console.WriteLine("Second handler")
Catch When i = 5
Console.WriteLine("Third handler")
End Try
End Sub
' Output: Third handler
El ejemplo siguiente tiene una instrucción Try…Catch incluida en un bloque Try .El bloque Catch interior produce una excepción que tiene su propiedad InnerException establecida en la excepción original.El bloque exterior Catch informa de su propia excepción y de la excepción interna.
Private Sub InnerExceptionExample()
Try
Try
' Set a reference to a StringBuilder.
' The exception below does not occur if the commented
' out statement is used instead.
Dim sb As System.Text.StringBuilder
'Dim sb As New System.Text.StringBuilder
' Cause a NullReferenceException.
sb.Append("text")
Catch ex As Exception
' Throw a new exception that has the inner exception
' set to the original exception.
Throw New ApplicationException("Something happened :(", ex)
End Try
Catch ex2 As Exception
' Show the exception.
Console.WriteLine("Exception: " & ex2.Message)
Console.WriteLine(ex2.StackTrace)
' Show the inner exception, if one is present.
If ex2.InnerException IsNot Nothing Then
Console.WriteLine("Inner Exception: " & ex2.InnerException.Message)
Console.WriteLine(ex2.StackTrace)
End If
End Try
End Sub
El ejemplo siguiente se muestra el control de excepciones para los métodos async.Para detectar una excepción que se aplique a una tarea async, la expresión de Await está en un bloque de Try del llamador, y la excepción se detecta en el bloque de Catch .
Quite los comentarios de la línea de Throw New Exception en el ejemplo para mostrar el control de excepciones.La excepción se detecta en el bloque de Catch , la propiedad de IsFaulted de la tarea se establece en True, y la propiedad de Exception.InnerException de la tarea se establece en la excepción.
Quite los comentarios de la línea de Throw New OperationCancelledException para mostrar qué ocurre al cancelar un proceso asincrónico.La excepción se detecta en el bloque de Catch , y la propiedad de IsCanceled de la tarea se establece en True.Sin embargo, en algunas condiciones que no se aplican a este ejemplo, IsFaulted se establece en True y IsCanceled se establece en False.
Public Async Function DoSomethingAsync() As Task
Dim theTask As Task(Of String) = DelayAsync()
Try
Dim result As String = Await theTask
Debug.WriteLine("Result: " & result)
Catch ex As Exception
Debug.WriteLine("Exception Message: " & ex.Message)
End Try
Debug.WriteLine("Task IsCanceled: " & theTask.IsCanceled)
Debug.WriteLine("Task IsFaulted: " & theTask.IsFaulted)
If theTask.Exception IsNot Nothing Then
Debug.WriteLine("Task Exception Message: " &
theTask.Exception.Message)
Debug.WriteLine("Task Inner Exception Message: " &
theTask.Exception.InnerException.Message)
End If
End Function
Private Async Function DelayAsync() As Task(Of String)
Await Task.Delay(100)
' Uncomment each of the following lines to
' demonstrate exception handling.
'Throw New OperationCanceledException("canceled")
'Throw New Exception("Something happened.")
Return "Done"
End Function
' Output when no exception is thrown in the awaited method:
' Result: Done
' Task IsCanceled: False
' Task IsFaulted: False
' Output when an Exception is thrown in the awaited method:
' Exception Message: Something happened.
' Task IsCanceled: False
' Task IsFaulted: True
' Task Exception Message: One or more errors occurred.
' Task Inner Exception Message: Something happened.
' Output when an OperationCanceledException or TaskCanceledException
' is thrown in the awaited method:
' Exception Message: canceled
' Task IsCanceled: True
' Task IsFaulted: False
El ejemplo siguiente se muestra el control de excepciones donde varias tareas pueden producir excepciones.El bloque de Try tiene la expresión de Await para la tarea que Task.WhenAll devolvió.Finaliza la tarea cuando se completan las tres tareas a las que se aplica Task.WhenAll .
Cada una de las tres causas de tareas una excepción.El bloque de Catch recorre las excepciones, que se encuentran en la propiedad de Exception.InnerExceptions de la tarea que Task.WhenAll devolvió.
Public Async Function DoMultipleAsync() As Task
Dim theTask1 As Task = ExcAsync(info:="First Task")
Dim theTask2 As Task = ExcAsync(info:="Second Task")
Dim theTask3 As Task = ExcAsync(info:="Third Task")
Dim allTasks As Task = Task.WhenAll(theTask1, theTask2, theTask3)
Try
Await allTasks
Catch ex As Exception
Debug.WriteLine("Exception: " & ex.Message)
Debug.WriteLine("Task IsFaulted: " & allTasks.IsFaulted)
For Each inEx In allTasks.Exception.InnerExceptions
Debug.WriteLine("Task Inner Exception: " + inEx.Message)
Next
End Try
End Function
Private Async Function ExcAsync(info As String) As Task
Await Task.Delay(100)
Throw New Exception("Error-" & info)
End Function
' Output:
' Exception: Error-First Task
' Task IsFaulted: True
' Task Inner Exception: Error-First Task
' Task Inner Exception: Error-Second Task
' Task Inner Exception: Error-Third Task
Vea también
Referencia
Exit (Instrucción, Visual Basic)
Instrucción On Error (Visual Basic)
Throw (Instrucción, Visual Basic)