Whenever an object is destroyed and removed from memory, the object's destructor is called. In object-oriented programming, a destructor gives an object a last chance to clean up any memory it allocated or perform any other tasks that must be completed before the object is destroyed.
Like constructors, destructors are defined as subroutines in the class definition. Visual Basic .NET uses two destructor methods, each with distinct differences:
The Finalize() subroutine is called automatically by the .NET Framework if it's defined in the object's class.
The Dispose() subroutine isn't called automatically by the .NET Framework; therefore, the application is responsible for calling it before an object is destroyed.
An object class should define the Finalize() method only if the object must execute some code at memory cleanup. But that code must not be time dependent or rely on the existence of other objects. The Finalize() method is called automatically by the memory manager within .NET. Because some overhead is involved with the Finalize() method being called, don't define this method in a class unless it needs one.
Finalize() should also be defined as protected so that another class can't call it directly. If a class inherits another class, it should call MyBase.Finalize() from within its Finalize() subroutine.
An example of a Finalize() destructor follows:
Overrides Protected Sub Finalize() ' Clean up class ' Call my base class's Finalize() MyBase.Finalize() End Sub
Because the .NET Framework can destroy an object any time after its last reference is released, you have no way of knowing when the Finalize() subroutine will be called. Don't rely on other outside objects being available within Finalize() because they may be destroyed already.
Unlike Finalize(), Dispose() is a destructor subroutine that the .NET Framework doesn't call automatically. If an object must perform cleanup at a specific point, defining a Dispose() subroutine is the correct option.
When a Dispose() subroutine is defined, it's up to an object's user to call Dispose() when the object is no longer needed. As with the Finalize() method, Dispose() should also call MyBase.Dispose() if it inherits another class.
It's not uncommon for a class definition to have both Finalize() and Dispose() destructors. Finalize() calls the Dispose() destructor to actually perform the cleanup. Having both destructors gives an object the best of both worlds. The object cleans itself up when it's destroyed and also gives the user a mechanism to force the object to clean itself up with Dispose().
The following sample code segment shows the definition of a Dispose() subroutine:
Overrides Protected Sub Dispose(ByVal IsDisposing As Boolean) ' Clean up class ' Call my base class's Dispose() MyBase.Dispose(IsDisposing) End Sub