Deterministic Disposal in VB.NET: Mastering the Using Statement
Learn how the VB.NET Using statement guarantees timely cleanup of IDisposable resources, why it matters for file, DB, and COM handles, and what pitfalls to watch out for in real‑world code.
14 Aug 2026, 08:11 UTC

Why deterministic disposal matters in VB.NET
When a program opens a file, connects to a database, or creates a COM object, the operating system hands out a handle. If that handle is never released, the process can exhaust system resources, lock files, or leave orphaned connections. In unmanaged languages you must remember to free every handle, but in VB.NET the Using statement takes that burden off your shoulders.
The core idea is simple: a Using block guarantees that the Dispose method of any IDisposable object is called when the block exits, no matter how the exit occurs. Whether the code runs to completion, throws an exception, or even aborts because of an unhandled error, Dispose will run. That deterministic cleanup is the foundation of reliable, leak‑free applications.
Syntax and basic usage
The syntax is intentionally terse:
Using resource As New SomeType(args)
' Code that uses resource
End Using
Key points:
SomeTypemust implementSystem.IDisposable.- The
Usingblock can be nested, but each level adds a line of boilerplate. - The
resourcevariable is only in scope inside the block.
VB.NET 2010 introduced the Using With syntax, allowing multiple resources on one line:
Using a As New FileStream("a.txt", FileMode.Open),
b As New FileStream("b.txt", FileMode.Open)
' Use a and b
End Using
However, this form still requires all objects to be IDisposable and does not support IAsyncDisposable.
Worked example: custom disposable and exception safety
Below is a minimal console app that demonstrates the deterministic nature of Using. The example runs on .NET 6 or later.
Imports System
' A tiny class that writes to the console when disposed
Public Class Logger
Implements IDisposable
Private disposed As Boolean = False
Public Sub Log(message As String)
If disposed Then Throw New ObjectDisposedException(GetType(Logger).FullName)
Console.WriteLine(message)
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
If Not disposed Then
Console.WriteLine("Logger disposed")
disposed = True
End If
End Sub
End Class
Module Program
Sub Main()
Try
Using log As New Logger()
log.Log("Starting operation")
' Simulate an error
Throw New InvalidOperationException("Something went wrong")
End Using
Catch ex As Exception
Console.WriteLine("Caught: " & ex.Message)
End Try
End Sub
End Module
Execution flow:
- Enter
Usingblock –Loggerinstance created. - Call
Log– writes "Starting operation". - Throw exception – control leaves the block.
- VB.NET automatically calls
Dispose– prints "Logger disposed". - Exception propagates to
Catch– prints "Caught: Something went wrong".
Notice that the disposal message appears before the exception message, proving that Dispose runs even when an error occurs.
Trade‑offs and limitations
While Using is powerful, it has boundaries that developers should keep in mind:
- Only
IDisposableobjects: The statement cannot be used with non‑disposable types. For example, a plainStringor a custom class that does not implementIDisposablewill produce a compile‑time error. - No post‑block access: Variables declared inside
Usingare out of scope afterEnd Using. Any attempt to use them later will fail to compile, which can be restrictive if you need to return a resource to the caller. - Verbose nesting: When you need to manage several resources, each
Usingadds a line. Nested blocks can become hard to read. TheUsing Withsyntax mitigates this but still requires separate declarations. - Dispose exceptions: If
Disposethrows, it can mask the original exception. VB.NET will surface theDisposeexception, potentially hiding the real problem. WrapDisposelogic in a try‑catch if you anticipate errors. - Asynchronous disposal unsupported: The
Usingstatement does not work withIAsyncDisposable. For async cleanup you must use aTry…Finallyblock and callAwait resource.DisposeAsync()manually.
Practical checklist for safe resource handling
- Identify all objects that implement
IDisposable(files, DB connections, streams, COM objects, etc.). - Wrap each in a
Usingblock or useUsing Withfor multiple resources. - Verify that
Disposedoes not throw in normal operation; if it can, add a try‑catch insideDisposeor document the behavior. - For async resources, use
Try…FinallyandAwait DisposeAsync(). - Run unit tests that trigger exceptions inside the
Usingblock to confirm disposal occurs. - Profile the application to ensure no lingering handles after the block ends.
Take‑away
The VB.NET Using statement is a concise, reliable way to guarantee that IDisposable resources are released immediately when a block exits. By eliminating manual try‑finally boilerplate, it reduces the risk of leaks and keeps code readable. Just remember its limits: it only works with disposable types, disallows post‑block access, and doesn’t handle async disposal. With those caveats in mind, you can confidently use Using to write robust, resource‑safe VB.NET applications.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.