Error Handling and Exceptions

15.1 Structured Exception Handling (Try...Catch...Finally)

Order Catch blocks from the most specific to the most general.

Throw alone rethrows the current exception. Throw ex resets the stack trace (avoid it).

Exit Try leaves the Try block (the Finally block still runs).

Try
    Dim n = Integer.Parse(input)
    Dim result = 100 \ n
    Console.WriteLine(result)
Catch ex As FormatException
    Console.WriteLine("Not a valid number.")
Catch ex As DivideByZeroException
    Console.WriteLine("Cannot divide by zero.")
Catch ex As Exception When ex.Message.Contains("timeout")    ' exception filter (When)
    Console.WriteLine("Timeout occurred.")
Catch ex As Exception
    Console.WriteLine($"Unexpected error: {ex.Message}")
    Throw                                                     ' rethrow, preserving the stack trace
Finally
    Console.WriteLine("Cleanup always runs.")
End Try

15.2 Common Exception Types

Accessing a member on Nothing Bad conversion/cast Numeric overflow (checked by default in VB!) Integer division by zero

IndexOutOfRangeException / ArgumentOutOfRangeException ArgumentException / ArgumentNullException Invalid object state Missing dictionary key

FileNotFoundException / IOException / UnauthorizedAccessException

NotImplementedException / NotSupportedException TimeoutException, HttpRequestException, SqlException

VB checks integer overflow by default (C# doesn't). You can disable this with the project setting *Remove integer overflow checks* (<RemoveIntegerChecks>true</RemoveIntegerChecks>).

15.3 Throwing and Custom Exceptions

Public Class InsufficientFundsException
    Inherits Exception

    Public ReadOnly Property Shortfall As Decimal

    Public Sub New(message As String, shortfall As Decimal)
        MyBase.New(message)
        Me.Shortfall = shortfall
    End Sub

    Public Sub New(message As String, inner As Exception)
        MyBase.New(message, inner)
    End Sub
End Class

Sub Withdraw(amount As Decimal)
    If amount <= 0 Then Throw New ArgumentOutOfRangeException(NameOf(amount), "Must be positive.")
    If amount > Balance Then Throw New InsufficientFundsException("Insufficient funds", amount - Balance)
    Balance -= amount
End Sub

15.4 Exception Properties

ex.Message, ex.StackTrace, ex.InnerException, ex.Source, ex.GetType().Name, ex.Data, ex.ToString() (full details), and ex.GetBaseException().

15.5 Unstructured Error Handling (Legacy: On Error)

You can't mix On Error and Try...Catch in the same procedure. Use Try...Catch in VB.NET.

Sub LegacyStyle()
    On Error GoTo ErrorHandler
    Dim x = 1 \ 0
    Exit Sub
ErrorHandler:
    Console.WriteLine($"Error {Err.Number}: {Err.Description}")
    Resume Next          ' continue with the next statement (dangerous)
End Sub
' On Error Resume Next ignores errors entirely. Avoid it in VB.NET (it's common in VBA/VB6).

15.6 Exception Handling Best Practices

Catch only what you can handle. Don't swallow exceptions silently.

Use TryParse / TryGetValue instead of exceptions for expected situations.

Use Using for resources (Module 24). Log exceptions with context.

Global handlers: AppDomain.CurrentDomain.UnhandledException, Application.ThreadException (WinForms), My.Application.UnhandledException (VB Application Framework), TaskScheduler.UnobservedTaskException.