Working with Collections


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 Collections

All 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 ArrayList

The 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.

Table 4.3. ArrayList Properties

Property

Description

Capacity

Indicates (or sets) the size of the ArrayList.

Count

Returns the number of items contained in the list.

IsFixedSize

Indicates whether the ArrayList is a fixed size.

IsReadOnly

Indicates whether the ArrayList is read-only.

Item

Provides access to an individual item within the ArrayList. C# uses indexer [] notation.


Table 4.4. ArrayList Methods

Method

Description

Add

Adds an item to the end of the list

AddRange

Adds a list of items to the end of the ArrayList

Clear

Empties the list

Contains

Indicates whether the specified item is in the list

Getrange

Returns a subset of the ArrayList

IndexOf

Returns the index within the list where the specified item resides

Remove

Removes an item from the list

RemoveAt

Removes the item at a given index

Reverse

Reverses the order of the elements in the list

Sort

Sorts some or all of the ArrayList

ToArray

Converts the ArrayList into a fixed-length array of a given type


Listing 4.4 illustrates the use of the ArrayList using strings as the element type.

Listing 4.4. ArrayList Demo

using System; using System.Collections; namespace AlDemo {   class Program   {     static void Main(string[] args)     {       ArrayList al = new ArrayList();       al.Add("Every good boy deserves fudge");       al.Add("The quick brown fox...");       al.Add("A stitch in time saves nine.");       al.Add("A penny saved a day is 7 cents a week.");       Console.WriteLine("First item " + (string)al[0]);       Console.WriteLine(string.Format(         "List has {0} elements, capacity of {1}, is fixed size? {2}",         al.Count, al.Capacity, al.IsFixedSize));       Console.WriteLine(string.Format(         "Index of 'The quick brown fox...' within the list is {0}\n",         al.IndexOf("The quick brown fox...")));       al.Sort();       Console.WriteLine("Sorted list:");       foreach (string s in al)       {          Console.WriteLine(s);       }       Console.ReadLine();     }   } } 

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 Hashtable

The 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 System; using System.Collections; using System.Text; namespace HashtableDemo {   class Program   {   static void Main(string[] args)   {     Hashtable ht = new Hashtable();     // store favorite color of each     // user     ht.Add("kevin", "Green");     ht.Add("joe", "White");     ht.Add("bob", "Red");     ht.Add("Mary", "Pink");     ht.Add("Jane", "Yellow");     Console.WriteLine(       string.Format("There are {0} items in the hashtable.", ht.Count));     foreach (string user in ht.Keys)     {       Console.WriteLine(string.Format("{0}'s favorite color is {1}",         user, ht[user]));     }     Console.WriteLine("Stored colors:");     foreach (DictionaryEntry de in ht)     {       Console.WriteLine(string.Format("{0}:{1}", de.Key, de.Value));     }     Console.ReadLine();   }  } } 

Using the Queue

The 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.

Table 4.5. Queue Methods

Method

Description

Clear

Removes all items from the Queue

Enqueue

Adds an item to the end of the Queue

Dequeue

Returns and takes an item off the beginning of the Queue

Peek

Returns the item at the beginning of the Queue without removing it

ToArray

Converts the contents of the Queue to a fixed-length array of a given type


Listing 4.6 illustrates the use of the Queue collection.

Listing 4.6. Queue Demo

using System; using System.Collections; using System.Text; namespace QueueDemo {  struct Message  {    public string Text;    public string To;    public string From;  }  class Program  {   static void Main(string[] args)   {    Queue mq = new Queue();    Message m = new Message();    m.Text = "Sample Text";    m.To = "user1";    m.From = "user2";    mq.Enqueue(m);    m = new Message();    m.Text = "Other Text";    m.To = "user3";    m.From = "user2";    mq.Enqueue(m);    Console.WriteLine(     string.Format("{0} messages to be processed.", mq.Count));    m = (Message)mq.Dequeue();    Console.WriteLine(     string.Format("De-queued message '{0}' ,{1} items remaining.",       m.Text, mq.Count));    m = (Message)mq.Dequeue();    Console.WriteLine(     string.Format("De-queued message '{0}' ,{1} items remaining.",       m.Text, mq.Count));    Console.ReadLine();   }  } } 

Using the Stack

The 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 System; using System.Collections; using System.Text; namespace StackDemo {  class Program  {   static void Main(string[] args)   {     Stack s = new Stack();     s.Push("Houston");     s.Push("New York");     s.Push("Los Angeles");     Console.WriteLine(s.Count.ToString());     foreach (String str in s)     {       Console.WriteLine(str);     }     string city = (string)s.Pop();     Console.WriteLine(city);     string city2 = (string)s.Peek();     Console.WriteLine(city2);     Console.ReadLine();    }  } } 

Using the SortedList

The 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.



Microsoft Visual C# 2005 Unleashed
Microsoft Visual C# 2005 Unleashed
ISBN: 0672327767
EAN: 2147483647
Year: 2004
Pages: 298

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