Exception Handling
Prerequisites: Classes and objects
When something goes wrong at run time, .NET throws an exception. You
handle it with Try ... Catch ... Finally ... End Try.
Module Program
Function SafeDivide(a As Integer, b As Integer) As Integer?
Try
Return a \ b
Catch ex As DivideByZeroException
Console.WriteLine($" ({ex.Message})")
Return Nothing
End Try
End Function
Sub Main()
Console.WriteLine(SafeDivide(10, 2))
Console.WriteLine(SafeDivide(10, 0).HasValue)
End Sub
End Module
5
(Attempted to divide by zero.)
False
Integer? is a nullable Integer that can also be Nothing (see
Nullable Values and Nothing later in this level).
Several Catch blocks and Finally
Module Program
Sub Process(text As String)
Try
Dim n = Integer.Parse(text)
Console.WriteLine($" 100 / {n} = {100 \ n}")
Catch ex As FormatException
Console.WriteLine($" not a number: '{text}'")
Catch ex As DivideByZeroException
Console.WriteLine(" can't divide by zero")
Catch ex As Exception
Console.WriteLine($" unexpected: {ex.Message}")
Finally
Console.WriteLine($" finished '{text}'")
End Try
End Sub
Sub Main()
For Each entry In {"4", "abc", "0"}
Process(entry)
Next
End Sub
End Module
100 / 4 = 25
finished '4'
not a number: 'abc'
finished 'abc'
can't divide by zero
finished '0'
- Catch blocks are tested in order — put specific exceptions first
and
Exception(which catches everything) last. Finallyalways runs, whether or not an exception happened — use it for cleanup.Catch ex As Exception When conditionadds a filter.
Throwing exceptions
Public Class InsufficientFundsException
Inherits Exception
Public ReadOnly Property Shortfall As Decimal
Public Sub New(shortfall As Decimal)
MyBase.New($"Insufficient funds: short by {shortfall}.")
Me.Shortfall = shortfall
End Sub
End Class
Module Program
Function Withdraw(balance As Decimal, amount As Decimal) As Decimal
If amount <= 0 Then Throw New ArgumentOutOfRangeException(NameOf(amount), "Amount must be positive.")
If amount > balance Then Throw New InsufficientFundsException(amount - balance)
Return balance - amount
End Function
Sub Main()
Try
Console.WriteLine(Withdraw(100D, 30D))
Console.WriteLine(Withdraw(100D, 250D))
Catch ex As InsufficientFundsException
Console.WriteLine($"{ex.Message} (Shortfall = {ex.Shortfall})")
End Try
Try
Withdraw(100D, -5D)
Catch ex As ArgumentOutOfRangeException
Console.WriteLine(ex.ParamName)
End Try
End Sub
End Module
70
Insufficient funds: short by 150. (Shortfall = 150)
amount
Throw New SomeException(...)raises an exception.- Custom exceptions inherit from
Exceptionand can carry extra data. NameOf(amount)gives"amount"as a string that stays correct if you rename the parameter.- Inside a
Catch, a bareThrowrethrows the current exception without losing its stack trace.
Using: automatic cleanup
Objects that hold resources (files, connections) implement
IDisposable. A Using block disposes them when it ends — even if an
exception occurs:
Public Class Resource
Implements IDisposable
Public Sub New()
Console.WriteLine("opened")
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Console.WriteLine("closed")
End Sub
End Class
Module Program
Sub Main()
Try
Using r As New Resource()
Console.WriteLine("working")
Throw New InvalidOperationException("something broke")
End Using
Catch ex As InvalidOperationException
Console.WriteLine($"caught: {ex.Message}")
End Try
End Sub
End Module
opened
working
closed
caught: something broke
On Error GoTo (legacy)
VB6 and VBA handle errors with On Error GoTo Handler and
On Error Resume Next. VB.NET still accepts them for compatibility, but
they can't be mixed with Try in the same procedure. Always use
Try/Catch in new code — From VB6 to VB.NET in Level 3 shows how to
convert.
Common mistakes
- Empty
Catchblocks that swallow errors silently. - Using exceptions for normal decisions: check with
TryParse,File.Exists, orContainsKeyfirst when failure is expected.