ProgrammingVB.NET Developer

How to implement constructors (Sub New) and destructors (Finalize/Dispose) in Visual Basic, when to apply which methods and what are the specifics of their invocation?

Pass interviews with Hintsage AI assistant

Answer.

In Visual Basic, a constructor is a Sub New procedure that is called when creating an instance of a class and initializes the object. A destructor is implemented using the Finalize method or the IDisposable interface (Dispose method), which is particularly important for releasing resources.

In classic Visual Basic, the constructor was automatically called when creating objects (Class_Initialize), and the destructor was called upon deletion (Class_Terminate). In VB.NET, overloaded constructors, separation of managed and unmanaged resource releases, and the use of garbage collector (GC) were added.

Problem

Incorrect use of constructors or destructors leads to memory leaks, incorrect object initialization, or resource locking (e.g., files).

Solution

Use Sub New for object initialization, and always implement Dispose for explicit resource release. When using a destructor (Finalize), be aware of GC latency and the inability to predict the time of invocation.

Code example:

Public Class ResourceHolder Implements IDisposable Private resource As SomeResource Public Sub New() resource = New SomeResource() Console.WriteLine("Resource allocated") End Sub Protected Overrides Sub Finalize() Dispose(False) MyBase.Finalize() End Sub Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Protected Overridable Sub Dispose(disposing As Boolean) If disposing Then If resource IsNot Nothing Then resource.Release() resource = Nothing End If End If End Sub End Class

Key features:

  • Sub New is always called when creating an object (New)
  • Dispose is for explicitly releasing resources (e.g., files), while Finalize protects against leaks during implicit release
  • Always call GC.SuppressFinalize(this) within Dispose to prevent double cleanup

Trick questions.

Can you manually call the Sub New constructor on an already existing object?

No, the constructor is called only when creating an object. For reinitialization, use a separate Reset method or similar.

When is Finalize called, and is its execution always guaranteed?

Finalize is called by the garbage collector when an object is destroyed, but its execution is not guaranteed (e.g., during a process crash or power failure).

Why is it necessary to call GC.SuppressFinalize inside Dispose?

This prevents the Finalize from being called again for an already manually freed object, increasing performance and preventing memory leaks.

Common mistakes and antipatterns

  • Not releasing unmanaged resources (e.g., file descriptors)
  • Directly calling Finalize (this is not allowed — it is called only by the garbage collector)
  • Absence of GC.SuppressFinalize in Dispose

Real-life examples

Negative case

In the project, Dispose was not implemented, and several files remained locked after the application ended — resources were not released until the garbage collector intervened.

Pros:

  • Less code

Cons:

  • Resource leaks
  • Failures upon re-launching the program

Positive case

Implemented IDisposable and Dispose, used Using when working with external resources. All files close correctly and the application runs stably.

Pros:

  • No leaks
  • Increased reliability

Cons:

  • Requires discipline during coding