Object Lifetime: How Objects Are Created and Destroyed
Objects begin life when an instance of a class is created using the New keyword. New objects often require initialization tasks to be performed before they are used for the first time. Common initialization tasks include opening files, connecting to a database, and reading the values of registry keys. Microsoft Visual Basic .NET controls the initialization of new objects using procedures called constructors.
Objects end life after they leave scope and are released by the common language runtime (CLR). Visual Basic .NET controls the release of system resources using procedures called destructors. Together, constructors (special methods that allow control over initialization) and destructors support the creation of robust and predictable class libraries.
Sub New and Sub Finalize
The Sub New and Sub Finalize procedures in Visual Basic .NET initialize and destroy objects; they replace the Class_Initialize and Class_Terminate methods used in previous versions of Visual Basic. Unlike Class_Initialize, the Sub New constructor can run only once when a class is created, and it cannot be called explicitly anywhere other than in the first line of code in another constructor from either the same class or from a derived class. Furthermore, the code in the Sub New method always runs before any other code in a class. Visual Basic .NET implicitly creates a Sub New constructor at run time if you do not explicitly define a Sub New procedure for a class.
Before releasing objects, the CLR automatically calls the Finalize method for objects that define a Sub Finalize procedure. The Finalize method can contain code that needs to execute just before an object is destroyed, such as closing files and saving state information. There is a slight performance penalty for executing Sub Finalize, so you should define a Sub Finalize method only when you need to release objects explicitly.
The Finalize destructor is a protected method that can be called only from the class it belongs to, or from derived classes. The system calls Finalize automatically when an object is destroyed, so you should not explicitly call Finalize from outside of a derived class's Finalize implementation. Unlike Class_Terminate, which executed as soon as an object was set to nothing, there is usually a delay between when an object loses scope and when Visual Basic .NET calls the Finalize destructor. Visual Basic .NET allows for a second kind of destructor, named Dispose, which can be explicitly called at any time to release resources immediately.
Class instances often control resources not managed by the CLR, such as Windows handles and database connections. To supplement garbage collection, your classes can provide a mechanism to actively manage system resources if they implement the IDisposable interface. IDisposable has one method, Dispose, which clients should call when they finish using an object. You can use the implementation of Dispose to release resources and perform tasks such as closing files and database connections. Unlike the Finalize destructor, the Dispose method is not called automatically. Clients of a class must explicitly call Dispose when you want to release resources.
Garbage Collection and the Finalize Destructor
The .NET Framework uses a system called reference-tracing garbage collection that periodically releases unused resources. Previous versions of Visual Basic use a different system called reference counting to manage resources. Although both systems perform the same function automatically, there are a few important differences.
The CLR periodically destroys objects when the system determines that such objects are no longer needed. Objects are released more quickly when system resources are in short supply, and less frequently otherwise. The delay between when an object loses scope and when the CLR releases it means that, unlike with objects in previous versions of Visual Basic, you cannot determine exactly when the object will be destroyed. In such a situation, objects are said to have non-deterministic lifetime. In most cases, non-deterministic lifetime does not change how you write applications, as long as you remember that the Finalize destructor may not execute immediately when an object loses scope.
Another difference between the garbage collection systems involves the use of Nothing. To take advantage of reference counting, programmers using previous versions of Visual Basic sometimes assign Nothing to object variables in order to release the references those variables hold. If the variable holds the last reference to the object, the object's resources are released immediately. In Visual Basic .NET, while there may be cases in which this procedure is still valuable, performing it never causes the referenced object to release its resources immediately. The only time you should set a variable to Nothing is when its lifetime is long relative to how long it takes the garbage collector to detect orphaned objects.