The goal of generics is to create collections that are "type safe" but that can be reused at design time with any type. Thus, the designer of a generic List would like to be able to designate that the List class can hold any type of data, but a specific type will be declared when the List class is used, and the compiler will enforce the type safety. 17.2.1. Generic List ClassThe classic problem with the Array type is its fixed size. If you do not know in advance how many objects an array will hold, you run the risk of declaring either too small an array (and running out of room) or too large an array (and wasting memory). Suppose you create a program that gathers input from a web site. As you find objects (strings, books, values, etc.), you will add them to the array, but you have no idea how many objects you'll collect in any given session. The classic fixed-size array is not a good choice, as you can't predict how large an array you'll need. The List class is like an array whose size is dynamically increased as required. Lists provide a number of useful methods and properties. Some of the most important are shown in Table 17-2.
When you create a List, you do not define how many objects it will contain. Add to the List using the Add method, and the List takes care of its own internal bookkeeping, as illustrated in Example 17-4. Example 17-4. Working with a ListImports System.Collections.Generic Module Module1 Sub Main( ) Dim empList As New List(Of Employee) Dim intList As New List(Of Integer) For counter As Integer = 0 To 4 empList.Add(New Employee(counter + 100)) intList.Add(counter + 5) Next For Each val As Integer In intList Console.Write(val.ToString( ) + " ") Next Console.WriteLine(Environment.NewLine) For Each emp As Employee In empList Console.Write(emp.ToString( ) + " ") Next Console.WriteLine(Environment.NewLine) Console.WriteLine("empList.Capacity: {0}", empList.Capacity) End Sub End Module Public Class Employee Private employeeID As Integer Public Sub New(ByVal theID As Integer) Me.employeeID = theID End Sub Public Overrides Function ToString( ) As String Return employeeID.ToString( ) End Function Public Property EmpID( ) As Integer Get Return employeeID End Get Set(ByVal value As Integer) employeeID = value End Set End Property End Class Output: 0 5 10 15 20 100 101 102 103 104 empArray.Capacity: 8 With an Array class, you define how many objects the array will hold. If you try to add more than that, the Array class will throw an exception. With a List, you do not declare how many objects the List will hold. The List has a property, Capacity, which is the number of elements the List is capable of storing: public int Capacity { get; set; } The default capacity is eight. When you add the ninth element, the capacity is automatically doubled to 16. If you change the For loop to: For counter As Integer = 0 To 8 the output looks like this: 5 6 7 8 9 10 11 12 13 100 101 102 103 104 105 106 107 108 empList.Capacity: 16 You can manually set the capacity to any number equal to or greater than the count. If you set it to a number less than the count, the program will throw an exception of type ArgumentOutOfRangeException. 17.2.2. Implementing IComparableLike all collections, the List implements the Sort method, which allows you to sort any objects that implement IComparable. In the next example, you'll modify the Employee object to implement IComparable: Public Class Employee Implements IComparable(Of Employee) To implement the IComparable interface, the Employee object must provide a CompareTo method: Function CompareTo(ByVal rhs As Employee) As Integer _ Implements IComparable(Of IComparable.Employee).CompareTo Return Me.employeeID.CompareTo(rhs.employeeID) End Function The CompareTo method has been implemented to take an Employee as a parameter. The current Employee object must compare itself to the parameter and return -1 if it is smaller than the parameter, 1 if it is greater than the parameter, and 0 if it is equal to the parameter.
You are ready to sort the list of employees, empList. To see if the sort is working, you'll need to add integers and Employee instances to their respective lists with (pseudo)random values. To create the random values, you'll instantiate an object of class Random and call the Next method on the Random to return a pseudo-random number. The Next method is overloaded; one version allows you to pass in an integer that represents the largest random number you want. In this case, you'll pass in the value 10 to generate a random number between 0 and 10: Random r = new Random( ); r.Next(10); Example 17-5 creates and then sorts the two lists. Example 17-5. Sorting generic Lists usng IComparableImports System.Collections.Generic Module Module1 Sub Main( ) Dim empList As New List(Of Employee) Dim intList As New List(Of Integer) Dim r As New Random( ) For counter As Integer = 0 To 8 empList.Add(New Employee(r.Next(10) + 100)) intList.Add(r.Next(10)) Next For Each val As Integer In intList Console.Write(val.ToString( ) + " ") Next Console.WriteLine(Environment.NewLine) For Each emp As Employee In empList Console.Write(emp.ToString( ) + " ") Next Console.WriteLine(Environment.NewLine) intList.Sort( ) empList.Sort( ) Console.WriteLine("Sorted: ") For Each val As Integer In intList Console.Write(val.ToString( ) + " ") Next Console.WriteLine(Environment.NewLine) For Each emp As Employee In empList Console.Write(emp.ToString( ) + " ") Next End Sub End Module Public Class Employee Implements IComparable(Of Employee) Private employeeID As Integer Public Sub New(ByVal theID As Integer) Me.employeeID = theID End Sub Public Overrides Function ToString( ) As String Return employeeID.ToString( ) End Function Public Property EmpID( ) As Integer Get Return employeeID End Get Set(ByVal value As Integer) employeeID = value End Set End Property Function CompareTo(ByVal rhs As Employee) As Integer _ Implements IComparable(Of IComparable.Employee).CompareTo Return Me.employeeID.CompareTo(rhs.employeeID) End Function End Class Output: 5 3 7 8 3 8 4 9 7 102 106 100 106 101 107 109 109 106 Sorted: 3 3 4 5 7 7 8 8 9 100 101 102 106 106 106 107 109 109 The output shows that the integer array and Employee array were generated with random numbers. When sorted, the display shows the values have been ordered properly. |