This article is part two of two about the use of the Share keyword. Part one, Shared and Instance Members in VB.NET, covered the more frequently used shared methods and properties in VB.NET. This part covers the less well known use of shared variables, and includes an example showing why you might want to use one. Part three, Shared Events in VB.NET, covers what might be an even less well known technique, but still one that has a specific reason for being part of the language.
The most important thing to understand is why "share" is necessary. The reason has everything to do with "object oriented programming" (OOP) and how classes are "instantiated" into objects. Part one goes into this subject in more detail, so you might want to read that first if this concept is at all unclear. But, very briefly, a copy of a class has to be made before it can be used in code. This is called "instantiation". So, if your program uses an "Account" class, then the code has to create a copy with the New keyword ... perhaps you might name it "currentAccount" ... before you can use that class:
Dim currentAccount as New Account
You can create as many copies as you need for your program:
Dim pastAccount As New Account
And each copy has unique properties:
currentAccount.AccountNumber = "12345678" . . . pastAccount.AccountNumber = "87654321"
But what if you need a property to be the same for all copies? That's where the "Shared" modifier comes in:
Shared Property CustomerName As String
The illustration shows both shared and instance properties:
Click Here to display the illustration
Shared variables are only slightly different. Properties are fundamentally just public class variables with code that allows them to be used only through a defined interface (the "setter" and "getter" blocks). The only difference with shared variables is that they're private to the class, so they have to be used by code inside the class.
One of the most common reasons to use a shared variable in a class is to keep track of how often the class is instantiated. In other words, a "counter". Simply declare an integer variable as shared in the class and then add 1 to it in the New subroutine. Voila! You know how many copies of the class have been made.
Here's a slightly different example. You have undoubtedly seen how programs will assign a unique name to a project by attaching an integer - 1, 2, 3 and so on - to the name if there is a duplicate name already. Suppose you have a class that you wish to be instantiated by any number of independent classes. How do you know if a name has been used previously? The answer: a shared ArrayList saves all of the names.
Here's the class:
Public Class Account Public Sub New(aH As String) Dim aHLen As Integer = Len(aH) If handleList.Count > 0 Then For Each h In handleList If h = aH Then acSuffix += 1 aH = Left(aH, aHLen) aH &= CStr(acSuffix) End If Next End If handleList.Add(aH) acctHandle = aH Console.WriteLine( "New Account Instance Created: " & aH) End Sub Private Shared handleList As ArrayList = New ArrayList Private acSuffix As Integer = 0 Public Property acctHandle As String End Class
The handleList control will have the same content no matter how many instances of the class are made, so it can be checked every time the New constructor is executed. The extra code is just there to add the correct suffix integer. This code instantiates the class:
Dim firstInstance As New FirstInstance Dim secondInstance As New Account("HandleTwo") Dim thirdInstance As New Account("HandleOne") Dim fourthInstance As New Account("HandleTwo") . . . and so forth
Note that I instantiate another class on the first line. I did this just to demonstrate that the instantiation can come from anywhere the Account class is in scope. The list of all handles is listed as shown below.
Click Here to display the illustration
Even when the same handle is passed multiple times to instantiate a new Account class, a unique handle is saved as a property for that class.
Extra credit assignment!! In writing this article, I initially tried to find a way to prevent the class from being instantiated in the first place as part of the New constructor. But I couldn't find a way. If you know the answer to this, send me an email.