Try...Catch...Finally Instrução (Visual Basic)
Oferece uma forma de lidar com alguns ou com todos os possíveis erros que podem ocorrer em um determinado bloco de código e, ainda assim, executar o código.
Sintaxe
Try
[ tryStatements ]
[ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ]
[ Exit Try ] ]
[ Catch ... ]
[ Finally
[ finallyStatements ] ]
End Try
Partes
Termo | Definição |
---|---|
tryStatements |
Opcional. Instruções em que um erro pode ocorrer. Pode ser uma instrução composta. |
Catch |
Opcional. Vários blocos Catch permitidos. Se ocorrer uma exceção ao processar o bloco Try , cada instrução Catch será examinada em ordem textual para determinar se ela manipula a exceção, sendo que exception representa a exceção que foi gerada. |
exception |
Opcional. Qualquer nome de variável. O valor inicial de exception é o valor do erro gerado. Usado com Catch para especificar o erro capturado. Se omitida, a instrução Catch captura qualquer exceção. |
type |
Opcional. Especifica o tipo de filtro de classe. Se o valor de exception for do tipo especificado por type ou de um tipo derivado, o identificador ficará associado ao objeto de exceção. |
When |
Opcional. Uma instrução Catch com uma cláusula When captura exceções somente quando expression é avaliada como True . Uma cláusula When é aplicada somente depois de verificar o tipo da exceção e expression pode se referir ao identificador que representa a exceção. |
expression |
Opcional. Deve ser implicitamente conversível para Boolean . Qualquer expressão que descreva um filtro genérico. Normalmente usado para filtrar por número de erro. Usado com a palavra-chave When para especificar as circunstâncias sob as quais o erro é capturado. |
catchStatements |
Opcional. Instruções para lidar com erros que ocorrem no bloco Try associado. Pode ser uma instrução composta. |
Exit Try |
Opcional. Palavra-chave que sai da estrutura Try...Catch...Finally . A execução é retomada com o código imediatamente após a instrução End Try . A instrução Finally ainda será executada. Não permitido em blocos Finally . |
Finally |
Opcional. Um bloco Finally sempre é executado quando a execução deixa qualquer parte da instrução Try...Catch . |
finallyStatements |
Opcional. Instruções executadas após a conclusão de todos os outros processamentos de erros. |
End Try |
Termina a estrutura Try...Catch...Finally . |
Comentários
Se você espera que uma exceção específica possa ocorrer durante uma determinada seção de código, coloque o código em um bloco Try
e use um bloco Catch
para manter o controle e manipular a exceção se ocorrer.
A instrução Try…Catch
consiste em um bloco Try
seguido por uma ou mais cláusulas Catch
, que especificam os manipuladores para diferentes exceções. Quando uma exceção é lançada em um bloco Try
, o Visual Basic procura a instrução Catch
que manipula a exceção. Se uma instrução Catch
correspondente não for encontrada, o Visual Basic examinará o método que chamou o método atual e assim por diante na pilha de chamadas. Se nenhum bloco Catch
for encontrado, o Visual Basic exibirá uma mensagem de exceção sem tratamento para o usuário e interromperá a execução do programa.
Você pode usar mais de uma instrução Catch
em uma instrução Try…Catch
. Se você fizer isso, a ordem das cláusulas Catch
será significativa porque elas são examinadas em ordem. Catch as exceções mais específicas antes das menos específicas.
As condições de instrução a seguir Catch
são as menos específicas e serão catch todas as exceções derivadas da classe Exception. Normalmente, você deve usar uma dessas variações como o último bloco Catch
da estrutura Try...Catch...Finally
, depois de capturar todas as exceções específicas esperadas. O fluxo de controle nunca pode alcançar um bloco Catch
que siga qualquer uma dessas variações.
O
type
éException
, por exemplo:Catch ex As Exception
A instrução não tem nenhuma variável
exception
, por exemplo:Catch
Quando uma instrução Try…Catch…Finally
é aninhada em outro bloco Try
, o Visual Basic examina primeiro cada instrução Catch
no bloco Try
mais interno. Se nenhuma instrução Catch
correspondente for encontrada, a pesquisa prosseguirá para as instruções Catch
do bloco Try…Catch…Finally
externo.
As variáveis locais de um bloco Try
não estão disponíveis em um bloco Catch
porque são blocos separados. Se você quiser usar uma variável em mais de um bloco, declare a variável fora da estrutura Try...Catch...Finally
.
Dica
A instrução Try…Catch…Finally
está disponível como um snippet de código do IntelliSense. No Gerente de Snippets de Código, expanda Padrões de Código – If, For Each,TryCatch, Property etc. e Tratamento de Erros (Exceções). Para obter mais informações, consulte Snippets de Código.
Bloco Finally
Se você tiver uma ou mais instruções que precisam ser executadas antes que você saia da estado Try
, use um bloco Finally
. O controle passa para o bloco Finally
pouco antes de ele sair da estrutura Try…Catch
. Isso é verdadeiro mesmo se ocorrer uma exceção em qualquer lugar dentro da estrutura Try
.
Um bloco Finally
é útil para executar qualquer código que precise ser executado mesmo se houver uma exceção. O controle é passado para o bloco Finally
, independentemente de como o bloco Try...Catch
sai.
O código em um bloco Finally
é executado mesmo que seu código encontre uma instrução Return
em um bloco Try
ou Catch
. O controle não passa de um bloco Try
ou Catch
para o bloco Finally
correspondente nos seguintes casos:
Uma Instrução End é encontrada no bloco
Try
ouCatch
.Um StackOverflowException é lançado no bloco
Try
ouCatch
.
Não é válido transferir explicitamente a execução para um bloco Finally
. A transferência da execução de um bloco Finally
não é válida, exceto por meio de uma exceção.
Se uma instrução Try
não contiver pelo menos um bloco Catch
, ela deverá conter um bloco Finally
.
Dica
Se você não tiver exceções catch específicas, a instrução Using
se comportará como um bloco Try…Finally
e garantirá o descarte dos recursos, independentemente de como você sai do bloco. Isso é verdadeiro mesmo com uma exceção sem tratamento. Para obter mais informações, consulte Instrução using.
Argumento de exceção
O argumento exception
do bloco Catch
é uma instância da classe Exception ou uma classe que deriva da classe Exception
. A instância da classe Exception
corresponde ao erro que ocorreu no bloco Try
.
As propriedades do objeto Exception
ajudam a identificar a causa e o local de uma exceção. Por exemplo, a propriedade StackTrace lista os métodos chamados que levaram à exceção, ajudando você a encontrar onde o erro ocorreu no código. Message retorna uma mensagem que descreve a exceção. HelpLink retorna um link para um arquivo de Ajuda associado. InnerException retorna o objeto Exception
que causou a exceção atual ou retorna Nothing
se não houver nenhum Exception
original.
Considerações ao usar uma instrução Try…Catch
Use uma instrução Try…Catch
apenas para sinalizar a ocorrência de eventos de programa incomuns ou inesperados. Os motivos para isso incluem o seguinte:
Capturar exceções em tempo de execução cria sobrecarga adicional e provavelmente será mais lento do que a pré-verificação para evitar exceções.
Se um bloco
Catch
não for tratado corretamente, a exceção poderá não ser relatada corretamente aos usuários.O tratamento de exceções torna um programa mais complexo.
Nem sempre você precisa de uma instrução Try…Catch
para verificar se há uma condição que provavelmente ocorrerá. O exemplo a seguir verifica se um arquivo existe antes de tentar abri-lo. Isso reduz a necessidade de capturar uma exceção gerada pelo 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
Verifique se o código em blocos Catch
pode relatar corretamente exceções aos usuários, seja por meio do registro em log thread-safe ou de mensagens apropriadas. Caso contrário, as exceções podem permanecer desconhecidas.
Métodos assíncronos
Se marcar um método com o modificador Async, você poderá usar o operador Await no método. Uma instrução com o operador Await
suspende a execução do método até que a tarefa aguardada seja concluída. A tarefa representa um trabalho em andamento. Quando a tarefa que está associada ao operador Await
for concluída, a execução será retomada no mesmo método. Para obter mais informações, confira Fluxo de controle em programas assíncronos.
Uma tarefa retornada por um método Async pode terminar em um estado com falha, indicando que ela foi concluída devido a uma exceção sem tratamento. Uma tarefa também pode terminar em um estado cancelado, o que resulta na expulsão de OperationCanceledException
da expressão await. Para catch qualquer tipo de exceção, coloque a expressão Await
associada à tarefa em um bloco Try
e catch a exceção no bloco Catch
. Um exemplo é fornecido posteriormente neste tópico.
Uma tarefa pode estar em um estado com falha porque várias exceções foram responsáveis pela falha. Por exemplo, a tarefa pode ser o resultado de uma chamada para Task.WhenAll. Quando você espera uma tarefa, a exceção capturada é somente uma das exceções e não é possível prever qual exceção será capturada. Um exemplo é fornecido posteriormente neste tópico.
Uma expressão Await
não pode estar dentro de um bloco Catch
ou Finally
.
Iterators
Uma função iteradora ou um acessador Get
realiza uma iteração personalizada em uma coleção. Um iterador usa uma instrução Yield para retornar um elemento da coleção por vez. Você chama uma função iteradora usando uma instrução For Each...Next.
Uma instrução Yield
pode estar dentro de um bloco Try
. Um bloco Try
que contém uma instrução Yield
pode ter blocos Catch
e pode ter um bloco Finally
. Para obter um exemplo, confira Try Blocos.
Uma instrução Yield
não pode estar dentro de um bloco Catch
ou bloco Finally
.
Se o corpo For Each
(fora da função iteradora) lançar uma exceção, um bloco Catch
na função iteradora não será executado, mas um bloco Finally
na função iteradora será executado. Um bloco Catch
dentro de uma função iteradora captura apenas exceções que ocorrem dentro da função iteradora.
Situações de confiança parcial
Em situações de confiança parcial, como um aplicativo hospedado em um compartilhamento de rede, Try...Catch...Finally
não catch há exceções de segurança que ocorrem antes que o método que contém a chamada seja invocado. O exemplo a seguir, ao colocá-lo em um compartilhamento de servidor e executar desse local, produz o erro "System.Security.SecurityException: Request Failed". Para obter mais informações sobre exceções de segurança, confira a classe SecurityException.
Try
Process.Start("http://www.microsoft.com")
Catch ex As Exception
Console.WriteLine("Can't load Web page" & vbCrLf & ex.Message)
End Try
Em uma situação de confiança parcial, você precisa colocar a instrução Process.Start
em um Sub
separado. A chamada inicial para o Sub
falhará. Isso permite Try...Catch
a catch antes de Sub
que contém Process.Start
seja iniciado e a exceção de segurança produzida.
Exemplos
A estrutura de Try...Catch...Finally
O exemplo a seguir ilustra a estrutura da instrução 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.
Console.WriteLine("end of Try block")
Catch ex As Exception
' Show the exception's message.
Console.WriteLine(ex.Message)
' Show the stack trace, which is a list of methods
' that are currently executing.
Console.WriteLine("Stack Trace: " & vbCrLf & ex.StackTrace)
Finally
' This line executes whether or not the exception occurs.
Console.WriteLine("in Finally block")
End Try
End Sub
Exceção em um método chamado de um bloco de Try
No exemplo a seguir, o método CreateException
gera um NullReferenceException
. O código que gera a exceção não está em um bloco Try
. Portanto, o método CreateException
não manipula a exceção. O método RunSample
manipula a exceção porque a chamada para o método CreateException
está em um bloco Try
.
O exemplo inclui instruções Catch
para diversos tipos de exceções, ordenadas da mais específica para a mais geral.
Public Sub RunSample()
Try
CreateException()
Catch ex As System.IO.IOException
' Code that reacts to IOException.
Catch ex As NullReferenceException
Console.WriteLine("NullReferenceException: " & ex.Message)
Console.WriteLine("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
A instrução Catch When
O exemplo a seguir mostra como usar uma instrução Catch When
para filtrar em uma expressão condicional. Se a expressão condicional for avaliada como True
, o código no bloco Catch
será executado.
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
Instruções de Try
aninhadas
O exemplo a seguir tem uma instrução Try…Catch
contida em um bloco Try
. O bloco Catch
interno gera uma exceção que tem a propriedade InnerException
definida como a exceção original. O bloco Catch
externo relata a própria exceção e a exceção 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
Tratamento de exceções para métodos assíncronos
O exemplo a seguir ilustra o tratamento de exceção para métodos assíncronos. Para catch uma exceção que se aplica a uma tarefa assíncrona, a expressão Await
está em um bloco Try
do chamador e a exceção é capturada no bloco Catch
.
Remova a marca de comentário da linha Throw New Exception
no exemplo para demonstrar o tratamento de exceção. A exceção é capturada no bloco Catch
, a propriedade IsFaulted
da tarefa é definida como True
e a propriedade Exception.InnerException
da tarefa é definida como a exceção.
Remova a marca de comentário da linha Throw New OperationCancelledException
para demonstrar o que acontece quando você cancela um processo assíncrono. A exceção é capturada no bloco Catch
e a propriedade IsCanceled
da tarefa é definida como True
. No entanto, em algumas condições que não se aplicam a este exemplo, a propriedade IsFaulted
é definida como True
e IsCanceled
é definido como 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
Tratamento de várias exceções em métodos assíncronos
O exemplo a seguir ilustra a manipulação de exceção em que várias tarefas podem resultar em várias exceções. O bloco Try
tem a expressão Await
da tarefa retornada por Task.WhenAll. A tarefa é concluída quando as três tarefas às quais Task.WhenAll se aplica são concluídas.
Cada uma das três tarefas causa uma exceção. O bloco Catch
itera por meio de exceções, que são encontradas na propriedade Exception.InnerExceptions
da tarefa retornada por Task.WhenAll
.
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