Section 9.10. Shared Class Members


9.10. Shared Class Members

Each object of a class has its own copy of all the instance variables of the class. However, in certain cases, all class objects should share only one copy of a particular variable. A program contains only one copy of a Shared class variable in memory, no matter how many objects of the class have been instantiated. A Shared class variable represents class-wide informationall class objects share the same piece of data. The declaration of a Shared member begins with the keyword Shared.

Let us use a video game example to explain the need for Shared class-wide data. Suppose we have a video game in which Martians attack other space creatures. A Martian tends to be brave and willing to attack other space creatures when it is aware that there are at least four other Martians present. If there are fewer than five Martians present, a Martian becomes cowardly. For this reason, each Martian must know the martianCount. We could endow class Martian with a martianCount instance variable. If we were to do this, then every Martian would have a separate copy of the instance variable, and every time we create a Martian, we would have to update the instance variable martianCount in every Martian. The redundant copies waste space, and updating those copies is time-consuming. Worse yet, while we are updating the individual copies of martianCount, there will be periods of time during which some of these copies have not yet been updated, so we could have inconsistent bravery behavior among the Martians. Instead, we declare martianCount to be Shared so that martianCount is class-wide data. Each Martian can then see the martianCount as if it were instance data of that Martian, but Visual Basic maintains only one copy of the Shared martianCount to save space. We also save time, in that the Martian constructor increments only the Shared martianCountthere is only one copy, so we do not have to increment separate copies of martianCount for each Martian object. This also prevents inconsistent bravery behavior among the Martians.

Performance Tip 9.1

When a single copy of the data will suffice, use Shared class variables rather than instance variables to save storage and simplify program logic.


Shared class members have class scope. A class's Public Shared members can be accessed through the class name using the dot separator (e.g., className.sharedMember-Name). A class's Private Shared class members can be accessed by clients only indirectly through non-Private methods of the class. Shared class members are available as soon as the class is loaded into memory at execution time; like other variables with class scope, they exist for the duration of program execution, even when no objects of that class exist. To allow clients to access a Private Shared class member when no objects of the class exist, you must provide a non-Private Shared method or property.

Unlike non-Shared methods, a Shared method has no Me reference, because Shared class members exist independently of any class objects and even when there are no objects of that class. So a Shared method cannot access non-Shared class members.

Common Programming Error 9.4

Using the Me reference in a Shared method or Shared property is a compilation error.


Shared Constructors

When Shared variables require more complex initialization than can be accomplished in a Shared variable declaration, you can create a Shared constructor to initialize them. A Shared constructor is declared like an instance constructor, but is preceded by the Shared modifier and can be used only to initialize Shared variables. A Shared constructor is implicitly Public, must be declared with no parameters, cannot call other constructors of the class and is guaranteed to execute before a program creates any objects of the class or accesses any Shared class members. A class can have both a Shared constructor and a non-Shared parameterless constructor.

Common Programming Error 9.5

Explicitly declaring a Shared constructor Public is a compilation error, because a Shared constructor is Public implicitly.


Class Employee with Shared Variables

Class Employee (Fig. 9.10) demonstrates a Private Shared class variable and a Public Shared Property. The Shared class variable countValue is initialized to zero by default (line 6). It maintains a count of the number of Employee objects that have been instantiated and currently reside in memory, including objects that have already been marked for garbage collection but have not yet been reclaimed by the garbage collector.

Figure 9.10. Employee class objects share Shared variable.

  1  ' Fig. 9.10: Employee.vb  2  ' Class Employee uses Shared variable.  3  Class Employee  4     Private firstNameValue As String ' employee first name  5     Private lastNameValue As String ' employee last name  6     Private Shared countValue As Integer ' Employee objects in memory  7  8     ' Employee constructor  9     Public Sub New(ByVal first As String, ByVal last As String) 10        firstNameValue = first 11        lastNameValue = last 12        countValue += 1 ' increment shared count of employees 13        Console.WriteLine("Employee object constructor for "  & _ 14           firstNameValue  & " "  & lastNameValue) 15     End Sub ' New 16 17     ' finalizer method decrements Shared count of employees 18     Protected Overrides Sub Finalize() 19        countValue -= 1 ' decrement countValue 20        Console.WriteLine("Employee object finalizer for "  & _ 21           firstNameValue & " " & lastNameValue & "; count = "  & _ 22           countValue) 23     End Sub ' Finalize 24 25     ' return first name 26     Public ReadOnly Property FirstName() As String 27        Get 28           Return firstNameValue 29        End Get 30     End Property ' FirstName 31 32     ' return last name 33     Public ReadOnly Property LastName() As String 34        Get 35           Return lastNameValue 36        End Get 37     End Property ' LastName 38 39     ' property Count 40     Public Shared ReadOnly Property Count() As Integer 41        Get 42           Return countValue 43        End Get 44     End Property ' Count 45  End Class ' Employee 

When objects of class Employee exist, Shared member countValue can be used in any method of an Employee objectin this example, the constructor (lines 915) increments countValue (line 12) and method Finalize (lines 1823) decrements countValue (line 19). (Note that method Finalize is declared using keywords Protected and Overridesmethod Finalize's header must contain these keywords, which we discuss in Chapters 1011.) If no objects of class Employee exist, member countValue can be referenced through a call to Property Count (lines 4044)this Property is Shared, and therefore we do not have to instantiate an Employee object to call the Get method of the Property. Also, by declaring property Count as ReadOnly, we prevent clients from changing the value of countValue directly, thus ensuring that clients can change count-Value's value only under the tight control of class Employee's constructors and finalizer.

Testing Shared Variables

Module SharedTest (Fig. 9.11) demonstrates the Shared members of Fig. 9.10. Lines 5 6 use the ReadOnly Shared Property Count of class Employee to obtain the current value of countValue. No Employee objects exist yet, so we must call Count using the class name Employee. Lines 89 then instantiate two Employee objects, causing countValue to be incremented by 2. Lines 1314 print the countValue by using ReadOnly Shared Property Count. Lines 1721 display the names of the employees. Lines 2425 set these objects' references to Nothing, so that employee1 and employee2 no longer refer to the Employee objects. This "marks" the objects for garbage collection, because there are no more references to these objects in the program.

Figure 9.11. Shared class member demonstration.

  1  ' Fig. 9.11: SharedTest.vb  2  ' Demonstrates Shared members.  3  Module SharedTest  4     Sub Main()  5        Console.WriteLine("Employees before instantiation: " & _  6           Employee.Count) ' Count is a Shared property  7  8        Dim employee1 As New Employee("Susan", "Baker") ' call constructor  9        Dim employee2 As New Employee("Bob", "Blue") ' call constructor 10 11        ' output number of employees after instantiation 12        ' (use Shared property) 13        Console.WriteLine(vbCrLf & "Employees after instantiation " & _ 14           "(via Employee.Count): " & Employee.Count) 15 16        ' display names of first and second employees (using properties) 17        Console.WriteLine(vbCrLf & "Display names of employees " & _ 18           "(using properties)" & vbCrLf & "Employee 1: " & _ 19           employee1.FirstName & " " & employee1.LastName & vbCrLf & _ 20           "Employee 2: " & employee2.FirstName & " " & _ 21           employee2.LastName & vbCrLf) 22 23        Console.WriteLine("Marking employees for garbage collection") 24        employee1 = Nothing ' mark employee1 for garbage collection   25        employee2 = Nothing ' mark employee2 for garbage collection   26 27        Console.WriteLine() 28        Console.WriteLine("Explicitly invoking the garbage collector") 29        System.GC.Collect() ' request garbage collection               30     End Sub ' Main 31  End Module ' SharedTest 

Employees before instantiation: 0 Employee object constructor for Susan Baker Employee object constructor for Bob Blue Employees after instantiation (via Employee.Count): 2 Display names of employees (using properties) Employee 1: Susan Baker Employee 2: Bob Blue Marking employees for garbage collection Explicitly invoking the garbage collector Employee object finalizer for Bob Blue; count = 1 Employee object finalizer for Susan Baker; count = 0 



Common Programming Error 9.6

A compilation error occurs if a Shared method calls an instance (non-Shared) method in the same class by using only the name of the method. Similarly, a compilation error occurs if a Shared method attempts to access an instance variable in the same class by using only the name of the variable.


Normally, the garbage collector is not invoked directly by the user. Either the garbage collector reclaims the memory for objects when it deems garbage collection is appropriate, or the operating system recovers the unneeded memory when the program terminates. Line 29 uses PublicShared method Collect from class GC (namespace System) to request that the garbage collector execute. Before the garbage collector releases the memory occupied by the two Employee objects, it invokes method Finalize for each Employee object, which decrements the countValue value by a total of 2.

The last two lines of the sample output show that the Employee object for Bob Blue was finalized before the Employee object for Susan Baker. However, the output of this program on your system could differ. The garbage collector is not guaranteed to collect objects in a specific order, nor is it guaranteed to run at all before the program terminates.




Visual BasicR 2005 for Programmers. DeitelR Developer Series
Visual Basic 2005 for Programmers (2nd Edition)
ISBN: 013225140X
EAN: 2147483647
Year: 2004
Pages: 435

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net