Try...Catch...Finally Statement (Visual Basic)
Provides a way to handle some or all possible errors that may occur in a given block of code, while still running code.
Syntax
Try
[ tryStatements ]
[ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ]
[ Exit Try ] ]
[ Catch ... ]
[ Finally
[ finallyStatements ] ]
End Try
Parts
Term | Definition |
---|---|
tryStatements |
Optional. Statement(s) where an error can occur. Can be a compound statement. |
Catch |
Optional. Multiple Catch blocks permitted. If an exception occurs when processing the Try block, each Catch statement is examined in textual order to determine whether it handles the exception, with exception representing the exception that has been thrown. |
exception |
Optional. Any variable name. The initial value of exception is the value of the thrown error. Used with Catch to specify the error caught. If omitted, the Catch statement catches any exception. |
type |
Optional. Specifies the type of class filter. If the value of exception is of the type specified by type or of a derived type, the identifier becomes bound to the exception object. |
When |
Optional. A Catch statement with a When clause catches exceptions only when expression evaluates to True . A When clause is applied only after checking the type of the exception, and expression may refer to the identifier representing the exception. |
expression |
Optional. Must be implicitly convertible to Boolean . Any expression that describes a generic filter. Typically used to filter by error number. Used with When keyword to specify circumstances under which the error is caught. |
catchStatements |
Optional. Statement(s) to handle errors that occur in the associated Try block. Can be a compound statement. |
Exit Try |
Optional. Keyword that breaks out of the Try...Catch...Finally structure. Execution resumes with the code immediately following the End Try statement. The Finally statement will still be executed. Not allowed in Finally blocks. |
Finally |
Optional. A Finally block is always executed when execution leaves any part of the Try...Catch statement. |
finallyStatements |
Optional. Statement(s) that are executed after all other error processing has occurred. |
End Try |
Terminates the Try...Catch...Finally structure. |
Remarks
If you expect that a particular exception might occur during a particular section of code, put the code in a Try
block and use a Catch
block to retain control and handle the exception if it occurs.
A Try…Catch
statement consists of a Try
block followed by one or more Catch
clauses, which specify handlers for various exceptions. When an exception is thrown in a Try
block, Visual Basic looks for the Catch
statement that handles the exception. If a matching Catch
statement is not found, Visual Basic examines the method that called the current method, and so on up the call stack. If no Catch
block is found, Visual Basic displays an unhandled exception message to the user and stops execution of the program.
You can use more than one Catch
statement in a Try…Catch
statement. If you do this, the order of the Catch
clauses is significant because they are examined in order. Catch the more specific exceptions before the less specific ones.
The following Catch
statement conditions are the least specific, and will catch all exceptions that derive from the Exception class. You should ordinarily use one of these variations as the last Catch
block in the Try...Catch...Finally
structure, after catching all the specific exceptions you expect. Control flow can never reach a Catch
block that follows either of these variations.
The
type
isException
, for example:Catch ex As Exception
The statement has no
exception
variable, for example:Catch
When a Try…Catch…Finally
statement is nested in another Try
block, Visual Basic first examines each Catch
statement in the innermost Try
block. If no matching Catch
statement is found, the search proceeds to the Catch
statements of the outer Try…Catch…Finally
block.
Local variables from a Try
block are not available in a Catch
block because they are separate blocks. If you want to use a variable in more than one block, declare the variable outside the Try...Catch...Finally
structure.
Tip
The Try…Catch…Finally
statement is available as an IntelliSense code snippet. In the Code Snippets Manager, expand Code Patterns - If, For Each, Try Catch, Property, etc, and then Error Handling (Exceptions). For more information, see Code Snippets.
Finally block
If you have one or more statements that must run before you exit the Try
structure, use a Finally
block. Control passes to the Finally
block just before it passes out of the Try…Catch
structure. This is true even if an exception occurs anywhere inside the Try
structure.
A Finally
block is useful for running any code that must execute even if there is an exception. Control is passed to the Finally
block regardless of how the Try...Catch
block exits.
The code in a Finally
block runs even if your code encounters a Return
statement in a Try
or Catch
block. Control does not pass from a Try
or Catch
block to the corresponding Finally
block in the following cases:
An End Statement is encountered in the
Try
orCatch
block.A StackOverflowException is thrown in the
Try
orCatch
block.
It is not valid to explicitly transfer execution into a Finally
block. Transferring execution out of a Finally
block is not valid, except through an exception.
If a Try
statement does not contain at least one Catch
block, it must contain a Finally
block.
Tip
If you do not have to catch specific exceptions, the Using
statement behaves like a Try…Finally
block, and guarantees disposal of the resources, regardless of how you exit the block. This is true even with an unhandled exception. For more information, see Using Statement.
Exception argument
The Catch
block exception
argument is an instance of the Exception class or a class that derives from the Exception
class. The Exception
class instance corresponds to the error that occurred in the Try
block.
The properties of the Exception
object help to identify the cause and location of an exception. For example, the StackTrace property lists the called methods that led to the exception, helping you find where the error occurred in the code. Message returns a message that describes the exception. HelpLink returns a link to an associated Help file. InnerException returns the Exception
object that caused the current exception, or it returns Nothing
if there is no original Exception
.
Considerations when using a Try…Catch
statement
Use a Try…Catch
statement only to signal the occurrence of unusual or unanticipated program events. Reasons for this include the following:
Catching exceptions at run time creates additional overhead, and is likely to be slower than pre-checking to avoid exceptions.
If a
Catch
block is not handled correctly, the exception might not be reported correctly to users.Exception handling makes a program more complex.
You do not always need a Try…Catch
statement to check for a condition that is likely to occur. The following example checks whether a file exists before trying to open it. This reduces the need for catching an exception thrown by the OpenText method.
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
Ensure that code in Catch
blocks can properly report exceptions to users, whether through thread-safe logging or appropriate messages. Otherwise, exceptions might remain unknown.
Async methods
If you mark a method with the Async modifier, you can use the Await operator in the method. A statement with the Await
operator suspends execution of the method until the awaited task completes. The task represents ongoing work. When the task that's associated with the Await
operator finishes, execution resumes in the same method. For more information, see Control Flow in Async Programs.
A task returned by an Async method may end in a faulted state, indicating that it completed due to an unhandled exception. A task may also end in a canceled state, which results in an OperationCanceledException
being thrown out of the await expression. To catch either type of exception, place the Await
expression that's associated with the task in a Try
block, and catch the exception in the Catch
block. An example is provided later in this topic.
A task can be in a faulted state because multiple exceptions were responsible for its faulting. For example, the task might be the result of a call to Task.WhenAll. When you await such a task, the caught exception is only one of the exceptions, and you can't predict which exception will be caught. An example is provided later in this topic.
An Await
expression can't be inside a Catch
block or Finally
block.
Iterators
An iterator function or Get
accessor performs a custom iteration over a collection. An iterator uses a Yield statement to return each element of the collection one at a time. You call an iterator function by using a For Each...Next Statement.
A Yield
statement can be inside a Try
block. A Try
block that contains a Yield
statement can have Catch
blocks, and can have a Finally
block. For an example, see Try Blocks.
A Yield
statement cannot be inside a Catch
block or a Finally
block.
If the For Each
body (outside of the iterator function) throws an exception, a Catch
block in the iterator function is not executed, but a Finally
block in the iterator function is executed. A Catch
block inside an iterator function catches only exceptions that occur inside the iterator function.
Partial-trust situations
In partial-trust situations, such as an application hosted on a network share, Try...Catch...Finally
does not catch security exceptions that occur before the method that contains the call is invoked. The following example, when you put it on a server share and run from there, produces the error "System.Security.SecurityException: Request Failed." For more information about security exceptions, see the SecurityException class.
Try
Process.Start("http://www.microsoft.com")
Catch ex As Exception
Console.WriteLine("Can't load Web page" & vbCrLf & ex.Message)
End Try
In such a partial-trust situation, you have to put the Process.Start
statement in a separate Sub
. The initial call to the Sub
will fail. This enables Try...Catch
to catch it before the Sub
that contains Process.Start
is started and the security exception produced.
Examples
The structure of Try...Catch...Finally
The following example illustrates the structure of the Try...Catch...Finally
statement.
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
Exception in a method called from a Try
block
In the following example, the CreateException
method throws a NullReferenceException
. The code that generates the exception is not in a Try
block. Therefore, the CreateException
method does not handle the exception. The RunSample
method does handle the exception because the call to the CreateException
method is in a Try
block.
The example includes Catch
statements for several types of exceptions, ordered from the most specific to the most general.
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
The Catch When statement
The following example shows how to use a Catch When
statement to filter on a conditional expression. If the conditional expression evaluates to True
, the code in the Catch
block runs.
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
Nested Try
statements
The following example has a Try…Catch
statement that is contained in a Try
block. The inner Catch
block throws an exception that has its InnerException
property set to the original exception. The outer Catch
block reports its own exception and the inner exception.
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
Exception handling for async methods
The following example illustrates exception handling for async methods. To catch an exception that applies to an async task, the Await
expression is in a Try
block of the caller, and the exception is caught in the Catch
block.
Uncomment the Throw New Exception
line in the example to demonstrate exception handling. The exception is caught in the Catch
block, the task's IsFaulted
property is set to True
, and the task's Exception.InnerException
property is set to the exception.
Uncomment the Throw New OperationCancelledException
line to demonstrate what happens when you cancel an asynchronous process. The exception is caught in the Catch
block, and the task's IsCanceled
property is set to True
. However, under some conditions that don't apply to this example, IsFaulted
is set to True
and IsCanceled
is set to 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
Handling multiple exceptions in async methods
The following example illustrates exception handling where multiple tasks can result in multiple exceptions. The Try
block has the Await
expression for the task that Task.WhenAll returned. The task is complete when the three tasks to which Task.WhenAll is applied are complete.
Each of the three tasks causes an exception. The Catch
block iterates through the exceptions, which are found in the Exception.InnerExceptions
property of the task that Task.WhenAll
returned.
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