Home > Articles > Programming > Windows Programming

This chapter is from the book

Using Constructors and Destructors

As with VB 6.0 classes, the classes in VB.NET support the inclusion of initialization and termination code that runs when a new instance of the class is created and deallocated. However, the names and behavior of these methods differ dramatically.

A constructor in VB.NET is defined as a procedure that has the name New (rather than Initialize as in VB 6.0) and can accept arguments to allow clients to pass data into the instance to assist with initialization. Constructors do not return values and therefore are always declared as a Sub. The constructor can also be overloaded and accept varying arguments to promote polymorphic use of the class.

When the first instance of a class is constructed using the New operator, the run-time will initially attempt to find and execute the shared constructor (defined as Shared Sub New()) on the class. Note that shared constructors are not defined with the Public keyword, cannot accept arguments, and hence cannot be overloaded with another version of the shared constructor. In other words, the following code is illegal because it attempts to overload a shared constructor:

Overloads Shared Sub New()
End Sub

Overloads Shared Sub New(ByVal ID As Integer)
End Sub

After dealing with the shared constructor, the runtime executes any virtual constructor (a constructor that is not shared), passing in the optional arguments, for the specific instance of the class. After that is completed, the instance is ready for use.

Inherited classes can also have their own shared and instance constructors. In this case, when a new instance of a derived class is created, the runtime first looks for a shared constructor of the base class, and then the shared constructor for the derived class, followed by an instance constructor for the derived class, and finally the instance constructor for the base class. This arrangement makes sense because the shared constructor of the derived class can alter the contents of other shared data and therefore must execute after the shared constructor of the base class.

If the derived class does not contain a shared constructor, the shared constructor of the base class is executed, followed by the instance constructor of the base class, and finally the instance constructor of the derived class.

This discussion implies that constructors cannot be overridden and will always execute regardless of whether a derived class has a constructor as well. As a result, you do not need to use the MyBase keyword to explicitly call the New method of the base class. However, you can invoke MyBase.New() as the first line in a instance constructor if you want to execute the constructor in the base class before that in the derived class.

Parameterized Constructors

The ability to pass data directly into the constructor is referred to as parameterized construction. VB.NET allows this by expanding the syntax for the New operator. For example, the Course class discussed earlier supports construction using the following syntax:

Protected Class Course
  Public Sub New(ByVal courseID As Integer)
    ' Initialize with a specific course in mind
  End Sub
  Public Sub New()
    ' Initialize without a course
  End Sub
End Class

A client then has the option of creating the class using either constructor by simply providing parameters to the New statement in the variable declaration:

Dim objCourse As New Course(intCourseID)

or separately in a New statement:

Dim objCourse As Course
objCourse = New Course(intCourseID)

Note that as an additional bonus, the IntelliSense feature of VS.NET shows both constructors in a drop-down list as shown in Figure 4.2.

Figure 4.2. Calling constructors. This screen shot from VS.NET shows how IntelliSense provides a drop-down list for all constructors of a class.

As with other overloaded methods, overloaded constructors must differ in either the number of arguments or their data types; argument names are not considered. Of course, in this simple example you could also have specified the courseID argument as Optional, although this would have required you to specify a default value and the IntelliSense feature would not show the varying constructors in a drop-down list. In addition, using overloaded constructors rather than optional arguments frees you from the limitation that each argument following the first optional must also be optional.

NOTE

Although it might seem confusing the Overloads keyword is not allowed on overloaded constructors.

By creating classes with numerous (overloaded) constructors, you also run the risk of duplicating code. You can alleviate duplication in one of two ways. First, you can create private procedures that abstract the non-specific initialization code required and simply invoke that procedure from each constructor. Second, you can place the non-specific initialization code in a shared constructor, although remember that shared constructors can reference only other shared members of the class.

Destructors

Analogous to the Terminate method in VB 6.0, each class in VB.NET can implement a Finalize method that is called when the object instance is deallocated. The Finalize method is a Sub procedure that should always be protected and overrides the Finalize method of the base class. However, unlike a constructor, the Finalize method of the base classes in the hierarchy do not run unless explicitly called with MyBase.Finalize in the derived class as follows:

Overrides Protected Sub Finalize
  ' Call the base class Finalize
  MyBase.Finalize
End Sub

Perhaps the most important difference between Terminate and Finalize, as mentioned in Chapter 1, is that by default, the Finalize method is actually executed by the runtime on a special thread allocated by the Garbage Collector (GC). Subsequent to the object instance no longer being referenced (reachable), the Finalize method is executed whenever the runtime feels it is appropriate, such as when a low-resource condition occurs. In other words, you don't necessarily have control of when the Finalize method executes. This situation is often referred to as non-deterministic finalization. VB.NET still supports the Nothing keyword and you are encouraged to set an object instance to Nothing when you are finished using it. This information actually helps the GC detect when an object is no longer reachable and allows it to be marked as requiring deallocation.

Using the Finalize method for code that frees resources such as file handles and database connections is tempting. However, because of non-deterministic finalization, you'll probably also want to free system resources much sooner than whenever the GC gets around to finalizing your objects.

NOTE

In fact, your classes do not have to implement a Finalize method at all. Not doing so actually increases performance for the runtime because the GC does not have to queue up the execution of the Finalize method, as mentioned in Chapter 1. However, in some cases you might want to make sure that all resources are cleaned up gracefully, and implementing a Finalize method is the only way to ensure that this happens.

The standard technique for allowing objects to clean up their resources in a timely fashion is to implement a Close or Dispose method in the class. Typically, a Close method is used when the object can be "opened" again by calling some other method, whereas Dispose is used if the object instance is not to be used after calling Dispose. Keep in mind that these methods will not automatically be called and so the documentation for your class must adequately describe its proper use. To provide both explicit and implicit cleanup, you can place your cleanup code in the Finalize method and then call Finalize from the Dispose method as shown in the following code:

Public Class Instructors
  Public Sub Dispose
    ' Dispose() calls Finalize so that you can include all 
    ' the cleanup code in one place.
    Me.Finalize()
    ' Tell the GC that the object doesn't require any cleanup
    GC.SuppressFinalize(Me)
  End Sub

  Overrides Protected Sub Finalize
    ' Clean up system resources
  End Sub
End Class

Note that the Finalize method can be called using the Me keyword because it is a member of the same object instance. In addition, the Services Framework makes available the System.GC class that you can use to interact with the Garbage Collector through its shared methods. In this case, the SuppressFinalize method is called to notify the GC that it does not have to Finalize this object because it has already been finalized. This saves the GC from having to do extra work when the object becomes unreachable.

One other aspect of the GC that you need to be aware of is that it does not guarantee that objects will be deallocated in any particular order. In other words, the order in which you set them to Nothing is not necessarily the order in which they'll be cleaned up.

This presents an interesting situation when you create one class that references another. For example, assume that the Registration class accepts an argument in its constructor that refers to an instance of the Instructors class defined in the previous code snippet as shown here:

Public Class Registration
  Private mIns As Instructors

  Public Sub New(ByRef obj As Instructors)
    mIns = obj
  End Sub

  Protected Overrides Sub Finalize()
    mIns.Dispose()
  End Sub
End Class

Obviously, as long as the Registration instance is reachable, the Instructors object will also be reachable because Registration retains a reference to it in the mIns local variable. However, let's assume that both instances become unreachable (are set to Nothing). Because the order of finalization is not guaranteed, the runtime could finalize the Instructors object referred to by the Registration object before the Registration object. In this case, when the finalization occurs on Registration and it attempts to call the Dispose method of Instructors, an exception is thrown. As a result, in designs like these you should either be prepared to catch the resulting exception or not implement a Finalize method in classes like Registration. Optionally, if the Instructors object really does need to be disposed, you can implement a Dispose method in Registration that calls the Dispose method of Instructors.

TIP

When you are dealing with classes that use external resources such as file handles, window handles, database connections, and other resources outside of the runtime, make sure that those resources are released with a finalizer and a Dispose method. However, if your classes simply manipulate other managed classes, either custom or through the Services Framework, you typically do not need to create a finalizer.

In order for other classes to call Dispose methods polymorphically in an early-bound fashion, the Services Framework exposes the IDisposable interface that your classes can implement. By implementing the interface, any client code can query for the interface and call an object's Dispose method without knowing anything else about the object. Windows Forms uses this technique to cleanup controls that are placed on a form. The Instructors class implementing IDisposable would look like Listing 4.10.

Listing 4.10 The Instructors class implementing the IDisposable interface to allow clients to call Dispose polymorphically.

Public Class Instructors
  Implements IDisposable

  Private mflDisposed As Boolean = False

  Public Sub Dispose Implements IDisposable.Dispose
    ' Dispose() calls Finalize so that you can include 
    ' all the cleanup code in one place.
    Me.Finalize()
    ' Tell the GC that the object doesn't require any cleanup
    GC.SuppressFinalize(Me)
    mflDisposed = True
  End Sub

  Overrides Protected Sub Finalize
    ' Clean up system resources
  End Sub

  Public Function GetInstructors() As DataSet
    If mflDisposed Then
      Throw ObjectDisposedException("Instructors")
    End If
  End Function
End Class

You'll also notice in Listing 4.10 that the class tracks a private Boolean variable to determine when the object was disposed. If any other method is subsequently called, such as GetInstructors, the System.ObjectDisposedException is thrown indicating to the client that the object is not usable.

Interacting with the GC

As the call to SuppressFinalize in the previous section makes clear, you can programmatically interact with the GC through the System.GC class through its shared methods.

The first method you can use to affect the GC is Collect. Basically, this method forces the GC to collect all unreachable objects and queue them up for finalization. Although it's possible to include this call in your code so that resources are cleaned up at a specific point in time, it is recommended that you design your classes to do explicit cleanup as discussed previously and then leave the actual collection process to the GC. In this way, resources that need to be freed early will be, and those that are less critical won't take up the extra CPU cycles being deallocated unnecessarily.

You can also call the KeepAlive method of System.GC and pass it a reference to an object you wish to not have garbage collected in the current method. When the runtime sees a call to KeepAlive, it assumes that the object is reachable up to the point where the KeepAlive method is called (in execution order within the current procedure, not necessarily in line order). In other words, the KeepAlive method assures that the object will be kept alive until at least directly after the call to KeepAlive. This method is sometimes used when referring to COM objects or other unmanaged objects so that the runtime does not inadvertently lose references to it.

Finally, you can also call the WaitForPendingFinalizers method, which suspends the current thread and waits for all Finalize methods that have been queued up to run. This is seldom used because this operation could take some time and block the current thread. In fact, WaitForPendingFinalizers is not assured ever to return (because the finalization process could trigger another garbage collection, ad infinitum) and so should be left safely alone.

Resurrection

As mentioned in Chapter 1, the runtime also allows objects to be re-referenced from within their Finalize methods. If this occurs, the object is said to be resurrected because it will not be deallocated and is now once again reachable. For example, assume that the Finalize method of the Registration class includes a line of code that passes a reference to the object using the Me keyword to another class or to a public variable within the application. In this case, the original variable used to refer to the Registration object would be set to Nothing; however, the object itself would still be alive and could be referenced through the new class or variable. The object is then said to be resurrected and can be used normally with the exception that the Finalize method will not run a second time. To allow it to run again, you must call the ReRegisterForFinalize method of the GC, passing in the Me keyword. The code for implementing the Registration class with resurrection is as follows:

Dim objHolder as Registration

Public Class Registration
  Private mIns As Instructors

  Public Sub New(ByRef obj As Instructors)
    mIns = obj
  End Sub

  Protected Overrides Sub Finalize()
    mIns.Dispose()

    ' Resurrect
    objHolder = Me
    GC.ReRegisterForFinalize(Me)
  End Sub
End Class

As a final note, keep in mind that as in this case shown here with mIns, if the resurrected class contains references to other objects, those references will also be resurrected.

Obviously, the situations in which you'd want to use resurrection are very limited, and as a general rule it should be avoided.

Weak References

The final way in which you can interact with the GC is to utilize weak references. Basically, as I discussed in Chapter 1, a weak reference is a reference to an object instance that can be collected by the GC if it deems that resources are scarce. In other words, by creating a weak reference, you are giving permission to the GC to collect the object even though you are still holding a reference to it, albeit a weak one. Of course, weak references imply the existence of strong references. A strong reference is simply one that is created with a standard variable using the New operator.

The idea behind weak references is to allow your application to hold references to many easily reconstructable objects without permanently consuming large amounts of memory. Obviously, the higher the cost of re-creating the object, the less likely it will be that you'll choose to use weak references. However, when you use a weak reference, there are a few coding conventions that must be followed.

To create a weak reference, you create an instance of the System.WeakReference class and pass it a strong reference to the object you want to hold. For example, the following code snippet creates a strong reference to the Instructors class followed by a weak reference:

Dim oIns As New Instructors
Dim wrIns As New WeakReference(oIns,False)

At this point, the oIns variable can go out of scope or otherwise become unreachable and the Instructors object will still be alive as long as the GC has not determined that it needs to reclaim memory by deallocating it. In the meantime, the wrIns variable can be passed around and perhaps stored in a collection for later use. The second argument to the WeakReference constructor shown earlier indicates whether the object should be available until the object is collected (False) or until it is actually finalized (True).

When the weakly referenced object needs to be used, you'll need to cast it to the correct type; however, you can first check to be sure that the object still exists by checking the Target property of the object. If the property is not Nothing, you can use the CType function to once again create a strong reference to the object.

Dim obj As Instructors

If Not wrIns.Target Is Nothing Then
  obj = CType(wrIns.Target, Instructors)
End If

Alternatively, you can check the IsAlive property to determine whether the object is still available, although doing so is discouraged because there is no guarantee that the object will still be alive even as soon as the very next statement.

At this point, the GC will not collect the object since it is reachable with a strong reference, and you can continue to work with it.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020