The Try...Catch...End Try Block
VB.NET's structured exception handling wraps risky code in a Try block; if a runtime error occurs, execution immediately jumps to a matching Catch block instead of crashing the program, and the whole construct closes with End Try. A Catch block can specify an exception type, such as Catch ex As FormatException, to handle only that category of error, and multiple Catch blocks can be stacked to handle different exception types differently, evaluated in order from most specific to most general.
Cricket analogy: A team's rain-interruption protocol is like a Try block: they attempt to complete 50 overs, but if a Catch (Rain) event occurs, they immediately switch to the Duckworth-Lewis-Stern recalculation instead of continuing the original plan as if nothing happened.
Multiple Catch Blocks and the When Filter
Stacking several Catch clauses lets a Try block respond differently depending on what actually went wrong — for example Catch ex As DivideByZeroException before a more general Catch ex As Exception, since VB.NET evaluates Catch blocks in order and uses the first type match. A When clause adds a further Boolean condition to a Catch, such as Catch ex As IOException When ex.Message.Contains("locked"), so the block only activates when both the exception type matches and the extra condition is true, otherwise the search continues to the next Catch.
Cricket analogy: A team's contingency plan stacks specific responses: Catch a rain delay first with the DLS method, then Catch a floodlight failure with a different fallback, and only Catch any other general disruption with abandoning the match, checked in that specific order.
The Finally Block
A Finally block, placed after all Catch blocks, always executes whether or not an exception occurred and whether or not it was caught — making it the right place to release resources like file handles, database connections, or network sockets that must be cleaned up regardless of outcome. In modern VB.NET, a Using block is often preferable for IDisposable resources since it automatically calls the equivalent of a Dispose() cleanup in a Finally block, but Finally remains essential for other cleanup logic like resetting a UI state or logging that an operation completed.
Cricket analogy: Regardless of whether a match is won, lost, or abandoned due to rain, the ground staff's Finally-block task of covering the pitch and collecting the stumps happens every single time once play concludes, exception or not.
Throwing Exceptions and Custom Exception Types
The Throw statement raises an exception, either a built-in .NET type like Throw New ArgumentException("Invalid input") or a custom class inheriting from Exception, letting a procedure signal a specific failure condition to its caller rather than silently returning an invalid result. Custom exceptions, declared as Public Class InsufficientFundsException : Inherits Exception, let large applications distinguish domain-specific errors from generic ones in Catch blocks; this structured approach has fully replaced the legacy On Error Goto and On Error Resume Next statements from classic VB, which are still supported for compatibility but are discouraged in new VB.NET code.
Cricket analogy: A DRS system throws a specific InsufficientEvidenceException equivalent when ball-tracking data is unclear, rather than silently guessing, forcing the on-field umpire's original decision to stand rather than pretending certainty exists where none does.
Module ErrorHandlingDemo
Public Class InsufficientFundsException
Inherits Exception
Public Sub New(message As String)
MyBase.New(message)
End Sub
End Class
Sub Main()
Try
WithdrawFunds(500D, 200D)
Catch ex As InsufficientFundsException
Console.WriteLine($"Withdrawal failed: {ex.Message}")
Catch ex As IOException When ex.Message.Contains("locked")
Console.WriteLine("Account file is locked, try again later.")
Catch ex As Exception
Console.WriteLine($"Unexpected error: {ex.Message}")
Finally
Console.WriteLine("Transaction attempt logged.")
End Try
End Sub
Sub WithdrawFunds(amount As Decimal, balance As Decimal)
If amount > balance Then
Throw New InsufficientFundsException(
$"Cannot withdraw {amount:C} from a balance of {balance:C}")
End If
Console.WriteLine("Withdrawal successful.")
End Sub
End ModuleUse a Using block instead of a manual Try/Finally when working with any IDisposable resource, such as a StreamReader or SqlConnection — Using guarantees Dispose() is called even if an exception occurs, with less boilerplate than writing the Finally block yourself.
Avoid the legacy On Error Goto and On Error Resume Next statements in new VB.NET code. On Error Resume Next in particular silently swallows errors and lets execution continue with potentially invalid state, making bugs far harder to diagnose than with structured Try/Catch, which forces you to explicitly decide how each exception type is handled.
- Try wraps risky code; Catch blocks handle specific exception types, evaluated in order from most specific to most general.
- Multiple Catch blocks can target different exception types, and a When clause adds an extra Boolean condition to a Catch.
- Finally always executes after a Try/Catch, whether or not an exception occurred, making it ideal for guaranteed cleanup.
- Using blocks are preferred over manual Finally blocks for IDisposable resources like file streams and database connections.
- Throw raises an exception, either a built-in .NET type or a custom class inheriting from Exception.
- Custom exception classes let large applications distinguish domain-specific failures from generic runtime errors in Catch blocks.
- Legacy On Error Goto and On Error Resume Next are discouraged in favor of structured Try/Catch/Finally.
Practice what you learned
1. What happens if no Catch block in a Try statement matches the thrown exception's type?
2. What is the purpose of a When clause on a Catch block?
3. When does a Finally block execute?
4. Which legacy VB error-handling statement is discouraged because it silently swallows errors?
5. How should a custom exception class typically be declared in VB.NET?
Was this page helpful?
You May Also Like
Subs and Functions in VB.NET
Understand how to organize reusable code in VB.NET using Sub and Function procedures, including parameters, return values, and overloading.
Optional and ByRef Parameters
Learn how VB.NET's Optional, ByRef, and ParamArray parameters give procedures flexible, efficient, and expressive argument-passing options.
Conditionals in VB.NET
Learn how to control program flow in VB.NET using If...Then...Else, Select Case, and logical operators to make decisions based on data.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics