.NET Generics for VB Programmers, Page 2
Defining a Generic Class
Generic classes are defined in the same instances that regular classes are defined, with one difference. A regular class is defined when you have data and more then one method that work as a cohesive unit or solution. Generic classes are defined when methods and data work as a cohesive unit and it is possible to abstract the data in such a way that multiple data types could be supported with the same code. For example, queues, lists, and stacks do not care what they store, just how they store it. If you use a queue, stack, or list of objects, then you have to perform messy type conversions all over your code. If you use a generic queue, stack, or list, then the type conversion occurs internally to the class. That is to say, the locus for the messy type conversions converge to an internal point in the class, and the class consumer can rely on compiler-checked types and isn't required to perform if-conditional checks and type conversions.
Defining a generic class is like defining multiple generic methods, with one addition: the (Of T) construct is used in the class header too. To demonstrate, you have a defined a generic strongly typed collection (see Listing 3) derived from System.Collections.CollectionBase. You can use this one class for any data type, as if you had defined a custom typed collection for all types:
Listing 3: A Generic Strongly Typed Collection
Module Module1
Sub Main()
Dim BrokenBones As TypedCollection(Of OrthoInjury) = _
New TypedCollection(Of OrthoInjury)
BrokenBones.Add(New OrthoInjury(True, _
"Broken Right Clavicle", "Vicodin; Heals n 8 to 12 weeks"))
BrokenBones.Add(New OrthoInjury(True, _
"Fractured Posterior Rib #5", "Heals in 6 to 8 weeks"))
BrokenBones.Add(New OrthoInjury(True, _
"Fractured Posterior Rib #1", "Heals in 6 to 8 weeks"))
Dim injury As OrthoInjury
For Each injury In BrokenBones
Console.WriteLine("Description: " & injury.Description)
Next
Console.ReadLine()
End Sub
End Module
Public Class TypedCollection(Of T)
Inherits System.Collections.CollectionBase
Default Public Property Item(ByVal Index As Integer) As T
Get
Return CType(List(Index), T)
End Get
Set(ByVal value As T)
List(Index) = value
End Set
End Property
Public Function Add(ByVal value As T) As Integer
Return List.Add(value)
End Function
End Class
Public Class OrthoInjury
Private FHasXray As Boolean
Private FDescription As String
Private FPrognosis As String
Public Sub New(ByVal HasXray As Boolean, _
ByVal Description As String, ByVal Prognosis As String)
FHasXray = HasXray
FDescription = Description
FPrognosis = Prognosis
End Sub
Public Property HasXray() As Boolean
Get
Return FHasXray
End Get
Set(ByVal value As Boolean)
FHasXray = value
End Set
End Property
Public Property Description() As String
Get
Return FDescription
End Get
Set(ByVal value As String)
FDescription = value
End Set
End Property
Public Property Prognosis() As String
Get
Return FPrognosis
End Get
Set(ByVal value As String)
FPrognosis = value
End Set
End Property
End Class
If you have read previous articles on typed collections, then you will see that the generic typed collection (in bold in Listing 3) is basically a strongly typed collection with the data type parameterized.
Using Predefined Generic Classes
Fortunately, you are not required to define generic classes from scratch. The System.Collections.Generic namespace defines many of the classic data structures, such as List, Queue, and Stack, as generics already. You simply have to import that namespace and declare an instance of the type you want. For example, the following code adequately replaces your custom typed collection with the .NET 2.0 generic List typed collection:
Dim BrokenBones As System.Collections.Generic.List(Of OrthoInjury) = _
New System.Collections.Generic.List(Of OrthoInjury)
As a general rule, if you want to store more than one type (heterogeneous types), use the older style classes like Queue and Stack. If you want to use just one type (homogeneous types), use the newer generic classes in the System.Collections.Generic namespace. Generally, you'll want the newer generic classes.
The Choice to Learn
Fewer and fewer things are separating traditionally complex languages like C++ from traditionally simpler languages like VB. At first glance, this fact can be frustrating because it implies VB is now harder to learnlike C++ is. In reality, the core language (VB) is pretty much the same, and just like C++, you always have the choice of learning more advanced idioms like generics if and when you need them. Now you aren't handicapped by absence of choice.
Also keep in mind that you always have the option of learning any programming idiom as a consumer firstuse what's there like generic Listsand then as a producer, learning how to create your own. Trying to master everything at once can be overwhelming and just isn't necessary.
About the Author
Paul Kimmel has written several books on object-oriented programming and .NET. Check out his upcoming book UML DeMystified from McGraw-Hill/Osborne (Spring 2005). Paul is also the founder and chief architect for Software Conceptions, Inc, founded 1990. He is available to help design and build software worldwide. You may contact him for consulting opportunities or technology questions at pkimmel@softconcepts.com.
