Collections are lists of data that don't necessarily need to be accessed by numerical index. In many cases, collections have custom index types and some collections, such as the Queue and Stack, don't support indexed access at all. This section begins by comparing and contrasting the various features of arrays and collections and offers some advice on how to decide between the two. Then you will get an overview of some of the collections provided by the .NET Framework. This section will not cover Generic collections, as those will be addressed in Chapter 6, "Introduction to Generics." Comparing Arrays and CollectionsAll arrays are indexed with integers, regardless of whether they are jagged arrays, rectangular arrays, or one-dimensional arrays. One main deciding factor is that arrays are generally faster to use. The main reason for this is that arrays are designed to be fixed-length and they are also all numerically indexed. A numerically indexed list of data is much faster at sequential access than a list of data that is accessed by a long string key such as a GUID. Some collections can use arbitrary objects as their keys. The tradeoff is performance versus functionality. If the data you need to store can possibly be stored as an array of fixed length (meaning the length doesn't change after initialization, not that you need to know the length at design time), that is definitely the way to go. However, you may need additional functionality provided by some of the classes described in the rest of the chapter. Collections are designed to store dynamic lists of data that can grow or shrink at runtime that may or may not be indexed numerically. If one of the Collection classes suits your needs, you may decide that it would be better to use that collection than to try to fit your data into an array. One final point of comparison is the ability to resize. Although all arrays can be resized by invoking Array.Resize, the performance penalty is pretty high. When you invoke that method, a new array of the appropriate size is created, and then each element from the existing array is copied into the new array. Although it's faster than doing this yourself manually, it still has a fairly high overhead, especially if you plan on resizing your array often. In short, arrays are generally of a fixed length while collections are designed to have a variable size. Using the ArrayListThe ArrayList functions much like an array, with a few extremely powerful exceptions. The most notable of these is the fact that you can dynamically add and remove items from the list at runtime without incurring the fairly large penalty for regular array resizing. ArrayLists, just like regular arrays, are accessed via a zero-based integer index. When you create a new ArrayList, it starts with a capacity of 0 and 0 items in the list. You then dynamically add and remove items programmatically via methods on the ArrayList class. One other thing to keep in mind before diving into the code for the ArrayList class is that the ArrayList considers nulls valid (so you can add a null to the list), and you can add the same value more than once. Before getting into the code, let's take a look at some of the properties and methods of the ArrayList class in Tables 4.3 and 4.4.
Listing 4.4 illustrates the use of the ArrayList using strings as the element type. Listing 4.4. ArrayList Demo
The output from this demo looks like this: First item Every good boy deserves fudge List has 4 elements, capacity of 4, is fixed size? False Index of 'The quick brown fox...' within the list is 1 Sorted list: A penny saved a day is 7 cents a week. A stitch in time saves nine. Every good boy deserves fudge The quick brown fox... Using the HashtableThe Hashtable is a special form of collection that stores name-value pair combinations like a traditional dictionary. The Hashtable is optimized, however, in that the object used as the indexer is hashed for more efficient access. What that all boils down to is that the Hashtable is extremely efficient at retrieving single values with keys of arbitrary data types, but is only as efficient as the other collection classes at being enumerated. Although the Hashtable accepts any kind of object as the key, one of the most common uses of the Hashtable is using strings as indices for data, as shown in the example in Listing 4.5. The code in Listing 4.5 shows you two different ways to iterate through the values and keys stored in the Hashtable, as well as how to directly access the data, add new data, and query Hashtable properties. Listing 4.5. Hashtable Demo
Using the QueueThe Queue is a special kind of collection. Unlike with most other collections, in Visual C# you don't have direct access to all of the items within the Queue. The Queue is a first-in, first-out collection of items. You enqueue an item when you place it in the collection and you dequeue an item when you obtain the first item in the collection. In several scenarios, the Queue class can be quite useful. If you are working with data that is handled in the order in which it was received, the Queue is the class to use. You cannot access individual items in a Queue tHRough an index, but you can obtain the number of items in the Queue with the Count property. Table 4.5 is a list of some common methods of the Queue class.
Listing 4.6 illustrates the use of the Queue collection. Listing 4.6. Queue Demo
Using the StackThe Stack class is a simple last-in first-out (LIFO) collection of objects. It works very much like the queue, except that the last item to be added to the Stack is going to be the next item that will come off the stack. Listing 4.7 provides a quick demonstration of the features of the Stack class. Listing 4.7. Stack Demo
Using the SortedListThe SortedList is a name/value collection where the items are sorted by the keys, and you can access the data within the collection both by the object key and by numerical index. When you add an item to the collection, it is then sorted based on the key of the item, as shown in the following example: SortedList sl = new SortedList(); sl.Add("Zippy Firecrackers", 24.99d); sl.Add("Aardvaark Candy", 52.99d); sl.Add("Mighty Bomb", 21.99d); sl.Add("Really Big Bomb", 33.99d); Console.WriteLine("Sorted List of Products:"); foreach (DictionaryEntry de in sl) { Console.WriteLine( string.Format("{0} costs {1:c}", de.Key, de.Value)); } Console.ReadLine(); The output from the preceding code shows how the items have been reordered to be properly sorted: Sorted List of Products: Aardvaark Candy costs $52.99 Mighty Bomb costs $21.99 Really Big Bomb costs $33.99 Zippy Firecrackers costs $24.99 The SortedList class provides a simple, easy-to-use means by which you can sort a list of items. A lot of user interface controls for both Web and Windows provide their own sorting code, but knowing that you can rely on the SortedList class for your own sorting can come in handy. |