Desktop Developer
Exploit Collections in VB
Take advantage of collections to both simplify and enhance your VB business applications.
Technology Toolbox: Visual Basic
The .NET Framework contains an extensive set of classes and interfaces for creating and managing collections of objects. Taking advantage of these in your applications can help you build applications faster and more quickly.
In particular, you should understand the various types of collection structures, what they are designed for, and when to use which. You should also learn how to use generics to create highly reusable, efficient collections.
I'll walk you through the various types of collections exposed by the .NET Framework, including how to work with arrays and array lists, how to use hashtables and dictionaries, how to implement queues and stacks, and how to create strongly typed and generic-based collections.
Programmers need to work with collections frequently. For example, if you work with employee time records in a payroll system, you need to group the records by employee, loop through the records, and add up the hours for each.
All collections need a basic set of functionality, such as adding objects, removing objects, and iterating through their objects. In addition to the basic set, some collections need additional specialized functionality. For example, a collection of help-desk e-mail requests needs to implement a first-in, first-out functionality when adding and removing items from the collection.
The .NET Framework provides a variety of basic and specialized collection classes for you to use. The System.Collections namespace contains interfaces and classes that define various collections of objects, such as lists, queues, hashtables, and dictionaries (see Table 1 and Table 2).
An array is one of the simplest data structures in computer programming. An array holds data elements of the same data type. For example, you can create an array of integers, strings, or dates. You access the elements of an array through its index. The index is an integer representing the position of the element in the index. For example, an array of strings representing the days of the week has these index values: Sunday = 0, Monday = 1, Tuesday = 2, and so on. This days of the week example is a one-dimensional array, which means the index is represented by a single integer. Arrays can also be multidimensional. The index of an element of a multidimensional array is a set of integers equal to the number of dimensions. For example, look at this seating chart, which represents a two-dimensional array
(see Figure 1).
You cannot explicitly derive from the Array class, but you implement array functionality when declaring an explicit type. For example, consider this code, which declares an array of type Integer:
Dim intArray() As Integer = {1, 2, 3, 4, 5}
You expose the properties and methods of the Array class once you declare the type as an array. Some of the functionality includes querying for the upper and lower bounds of the array, updating the elements of the array, and copying the elements of the array.
Declare and Manipulate Arrays
Declaring and working with an array of integers is straightforward (see Listing 1). You can also create multidimensional arrays. This code snippet declares and fills a two-dimensional array:
Dim int2DArray(2, 2) As Integer
For i As Integer = 0 To int2DArray.GetUpperBound(0)
For x As Integer = 0 To _
int2DArray.GetUpperBound(1)
int2DArray(i, x) = i + x
Next
Next
?Print the index and value of the elements
For i As Integer = 0 To int2DArray.GetUpperBound(0)
For x As Integer = 0 To _
int2DArray.GetUpperBound(1)
Console.WriteLine("index(" & i & "," & x & ")"
& ControlChars.Tab & "Value " &
int2DArray(i, x))
Next
Next
You often don't know the number of items contained in the collection until runtime when working with collections. You can resize an array using the Redim statement, but that isn't an efficient or convenient way of working with a dynamic arrays. This is where the ArrayList class fits in. The capacity of an array list expands automatically as required, with the memory reallocation and copying of elements performed automatically. The ArrayList class also provides methods for adding, inserting, or removing a range of elements, which Array does not provide (see Listing 2).
Working with an ArrayList is easier than working with an Array in many cases, but the ArrayList can have only one dimension. Also, an Array of a specific type has better performance than an ArrayList because the elements of ArrayList are of type Object.
Two special types of collections you use often in programming are the stack and the queue. A stack represents a last-in, first-out (LIFO) collection of objects. A queue represents a first-in, first-out (FIFO) collection of objects.
A good example of a stack is maintaining an approval list for an expense. When the expense is submitted up through a chain of managers, a stack maintains the list. After a top-level manager approves an expense, the next manager is retrieved from the list and sent a notification. You retrieve items on the list in the reverse order of how you added them in originally. Another example of using a stack occurs when a program executes a series of function calls. A stack maintains the addresses of the functions, and execution returns to the functions in the reverse order in which they were called. When placing items in a stack, you use the push method. The pop method removes items from the stack. The peek method returns the object at the top of the stack without removing it.
An application servicing help desk requests is a good example of when to use a queue. A collection maintains a list of help desk requests sent to the application. When requests are retrieved from the collection for processing, the first ones in should be the first ones retrieved. The Queue class uses the enqueue and dequeue methods to add and remove items. It also implements the peek method to return the item at the beginning of the queue without removing the item
(see Listing 3).
How to Use Hashtables
You often need to search through a collection for a particular item. If the items are stored in an Array or ArrayList structure, you need to loop through the entire collection until you find what you're looking for. This becomes increasingly inefficient as the collection grows. A better way to organize large collections is to group the items into subgroups based on an attribute of the item. For example, you can organize a baseball card collection into subgroups based on teams or positions played. You represent this type of collection in the .NET Framework by using a hashtable collection.
Each element in the hashtable is a DictionaryEntry structure, which consists of a key/value pair. The hashtable organizes the elements of the collection into buckets. A bucket is a virtual subgroup of elements associated with a hash code, generated using a hash function and based on the key of the element. Organizing the items into the buckets makes searching and retrieving information easier and faster (see Listing 4).
The .NET Framework also provides specialized collections that implement specific functionality more efficiently than the Hashtable class. For example, a StringDictionary class provides better performance when the keys used in the collection are constrained as a string type. Another collection type is the SortedList, which is a hybrid between the ArrayList and the Hashtable. As items are added to or removed from the collection, the SortedList maintains a sort order based on the key. You can access items by their index, just as you can with an ArrayList. You can also access the items by their key, similar to working with a hashtable. Be sure to consult the documentation for the System.Collections and the System.Collections.Specialized namespaces for a complete list of the various specialized collection classes provided by the .NET Framework.
Using Generics
The collections provided by the .NET Framework are weakly typed, except for few of specialized collections that hold strings. The items held by the collections are of type Object. This means they can be of any type, because all types derive from the Object type.
Weakly typed collections can cause performance and maintenance problems with your application. One problem is there are no inherent safeguards for limiting the types of objects stored in the collection. The same collection can hold any type of item, including dates, integers, or a custom type such as an employee object. If you build and expose a collection of integers, then inadvertently pass that collection a date, there is a good chance the code will fail at some point.
Fortunately, VB 2005 supports generics, and the .NET Framework provides generic-based collections in the System.Collections.Generic namespace. Generics offer the ability to define a class without specifying its type. The type is specified when the class is instantiated. Using a generic collection provides the advantages of type safety and performance of a strongly typed collection while also providing the code reuse associated with weakly typed collections.
Take a look at this example of a strongly typed collection of employees using the Generic.List class. You add Employee objects to the collection, and then retrieve the employees in the collection with the names written out to the console:
Dim emp1 As New employee(1, "Bob")
Dim emp2 As New employee(2, "Cathy")
Dim emp3 As New employee(3, "Alice")
Dim empCollection As New Generic.List(Of employee)
empCollection.Add(emp1)
empCollection.Add(emp2)
empCollection.Add(emp3)
For Each item As employee _
In empCollection
Console.WriteLine(item.Name)
Next
There might be times when you need to extend the functionality of the collections provided by the .NET Framework. For example, you might need a collection of employee objects that offers the ability to sort the collection by either the employee ID number or the employee last name. You can implement this functionality by creating a custom employee collection that inherits from, and extends, the Generic.List class (see Listing 5).
The code adds the three previous employees to the EmployeeCollection, sorts the collection by name, and writes the names out to the console:
Dim empCollection2 As New employeeCollection
empCollection2.Add(emp1)
empCollection2.Add(emp2)
empCollection2.Add(emp3)
empCollection2.Sort(employeeCollection.SortField.Name)
For Each item As employee _
In empCollection2
Console.WriteLine(item.Name)
Next
You should also have a firm understanding of how class structures, object collaboration, and collections are implemented in a VB application. It should be a relatively simple exercise to take your understanding of arrays, array lists, hashtables, dictionaries, queues, stacks, and generic-based and strongly typed collections, and apply it in real-world applications.
Editor's Note: This article is excerpted from "Chapter 6: Creating Classes" of Daniel R. Clark's book, Beginning Object-Oriented Programming With VB 2005 From Novice to Professional (ISBN: 1-59059-576-9). This book is published by Apress.