Team LiB
Previous Section Next Section

System.Collections

The System.Collections namespace contains interfaces and classes that define various collections of objects, such as lists, queues, arrays, hash tables, and dictionaries. Table 3-1 describes the nonstrong-typed collection classes.

Table 3-1: Nonstrong-Typed Collections

Class

Description

ArrayList

A dynamically sized array that can contain any sort of object.

BitArray

A compact array of bit values whose value can be either true or false.

Hashtable

A hash table that maps given keys to values allowing for buckets of segmented data. A hash table maintains a sorted list of key/ value pairs that can be accessed by a key value.

Queue

Represents a first-in, first-out collection of objects.

Stack

Represents a last-in, first-out collection of type Object.

Caution 

Each of these nonstrong-typed collection classes stores its contents as objects, which forces the contents to be boxed and placed on the heap. This could cause performance problems in your applications. Therefore, it is recommended that you use strong-typed collections or build your own collection with generics (see Chapter 5 for information about generics).

The strong-typed collection classes are described in Table 3-2.

Table 3-2: Strong-Typed Collections

Class

Description

CollectionBase

Provides an abstract base class, allowing you to derive your own strong-typed collection.

DictionaryBase

Provides an abstract base class, allowing you to create a derived class that stores a specific type. This type uses the associated key/value pairs.

ReadOnlyCollectionBase

Another abstract class. This type allows for read-only access.

We will discuss each major collection type in detail over the next few pages.

ArrayLists

An ArrayList is an array that has a dynamic size, so it can grow as necessary. ArrayLists can be used to store any type, including built-in types and custom types defined as classes.

A useful feature of an ArrayList is that it can be expanded on demand, if necessary. C# does this by creating a new instance of an ArrayList for the new size and copying the current members of the smaller ArrayList to the new ArrayList.

Caution 

Expanding an ArrayList on demand comes at a price. An ArrayList is a reference type, and when it is expanded by creating a new ArrayList, you must not count on the reference always being at the same address.

You can add members of an ArrayList using two methods: Add and Insert. You can remove members from an ArrayList by using the Remove, RemoveAt, or Clear method. These and other useful methods provided by an ArrayList are described in Table 3-3.

Table 3-3: Useful ArrayList Methods

Method

Description

Add

Adds a new member to the end of the array

Insert

Allows you to place the new member in the ArrayList at whatever location you choose

Remove

Removes the first occurrence of the parameter that you pass

RemoveAt

Removes a specific member at a specific location in the ArrayList

Clear

Removes all members of the ArrayList

Clone

Creates a shallow copy of the list

Equals

Determines if two objects are equal

Reverse

Reverses the order of the array

ToArray

Copies the members to a new array

ToString

Returns a string that represents the current object

The ArrayList also provides a field called count, which will tell you how many members are in the ArrayList at a given time.

To iterate through an ArrayList, you can use any of the iterator statements defined in Chapter 4. The foreach or for statements are recommended, because they will define your intent more clearly than the other iterator statements.

The following example demonstrates declaring an instance of an ArrayList that will contain an initial ten members. This example uses a foreach loop. Notice the first operand of the foreach loop is of the type placed in the ArrayList, and the second operand is the name given to the instance of the ArrayList.

Code Example: ArrayList
Start example
using System;
using System.Collections;

namespace Client.Chapter_3___Structs__Enums__Arrays_and_Collections
{
      class MyArrayList
      {
            static void Main(string[] args)
            {
                  //Creates an array with 10 members
                  ArrayList a = new ArrayList(10);
                  int x = 0;
                  //Adds a member to the end of the array
                  a.Add(x);
                  //Adds the value of 1 to position 2
                  a.Insert(1, ++x);
                  foreach (int y in a)
                  {
                        Console.WriteLine(y);
                  }
                  //Removes the last member of the array
                  a.Remove(x);
                  //Removes the member at position 0
                  a.RemoveAt(0);
                  //Removes all members of the array
                  a.Clear();
            }
      }
}
End example

Hashtables

Hashtables are a collection of associated keys and values that are organized based on the hash code of the key.

When an entry is added to the Hashtable, the entry is placed into a bucket based on the hash code of the key. Subsequent lookups of the key use the hash code of the key to search in only one particular bucket, thus substantially reducing the number of key comparisons required to find an entry.

The load factor of a Hashtable determines the maximum ratio of entries to buckets. Smaller load factors cause faster average lookup times, at the cost of increased memory consumption. The default load factor of 1.0 generally provides the best balance between speed and size. You can specify a different load factor when the Hashtable is instantiated.

As entries are added to a Hashtable, the actual load factor of the Hashtable increases. When the actual load factor reaches the default or specified load factor, the number of buckets in the Hashtable is automatically increased to the smallest prime number that is larger than twice the current number of Hashtable buckets.

To declare an a new Hashtable, you must call new with the number of entries that you expect, like this:

            Hashtable a = new Hashtable(10);

You can add entries to a Hashtable by calling the Add method and supplying the key as the first parameter, followed by the value in the second, as in these examples:

            a.Add(100, Arrays");
            a.Add(200, "Classes");

There are three types of exceptions that can be thrown when adding a new key to the Hashtable:

  • If you pass a null key, you will throw an exception of ArgumentNullException.

  • If you try to add an entry that already exists, an ArgumentException will be thrown.

  • If the Hashtable is read-only or of fixed length, a NotSupportedException will be thrown.

Note 

IDictionary is the underlying interface used to create Hashtables, DictionaryBase, and SortedList collections. This interface provides support for associated key/value pairs. It also allows for enumeration but does not imply a sorted collection. Some common methods supported by this interface are Add, Clear, Contains, GetEnumerator, and Remove.

Since each element of the Hashtable is a key/value pair, the element type is not the type of the key or the type of the value. Therefore, you must use a DictionaryEntry object as the type to iterate through the collection, as in this example:

            foreach(DictionaryEntry d in a)
            {
                  Console.WriteLine(d.Value);
            }

Finally, you can call the Remove and Clear methods to remove entries.

            a.Remove(100);
            a.Clear();
Note 

The Hashtable is the only built-in collection that has some thread safety. Specifically, it supports multiple readers and a single writer.

The following example demonstrates the use of Hashtables.

Code Example: Hashtables
Start example

using System;
using System.Collections;

namespace Client.Chapter_3___Structs__Enums__Arrays_and_Collections
{
      class HashTables
      {
            static void Main(string[] args)
            {
                  Hashtable a = new Hashtable(10);
                  //Marks the Hashtable as thread-safe
                  Hashtable.Synchronized(a);

                  //Adds a member to the table
                  a.Add(100, "Arrays");
                  a.Add(200, "Classes");

                  foreach(DictionaryEntry d in a)
                  {
                        Console.WriteLine(d.Value);
                  }
                  //Removes all members with the key of 100
                  a.Remove(100);
                  a.Remove(200);
                  //Removes all members
                  a.Clear();
            }
      }
}
End example

Queues

A Queue represents a first-in, first-out (FIFO) collection of objects. Queues should be used when the sequence of objects with regard to their order of entry is important to maintain. Queue entries are entered in one end of the collection and removed from the other end.

Caution 

Note that Queues are not thread-safe by default. Therefore, you must use the Synchronize method or lock keyword to ensure two threads do not access the same Queue simultaneously.

To create a new Queue, you must declare a new instance with the number of entries as the first parameter, like this:

            Queue a = new Queue(10);
              int x = 0;

You add entries to a Queue by using the Enqueue method and passing the item to be queued as the first parameter, as in this example:

            a.Enqueue(x);
            x++;
            a.Enqueue(x);

To iterate through a Queue, you can use a foreach statement. The first operand of the foreach loop is of the same type that was inserted into the queue with the Enqueue method. The second operand is the name of the Queue collection that was declared. Here is an example of using foreach to iterate through a Queue:

            foreach(int y in a)
              {
                   Console.WriteLine(y);
              }

To remove items from the Queue, call the Dequeue method. The oldest items are always removed from the Queue first.

            a.Dequeue();

If you want to clear the whole Queue at once, you can use the Clear method.

            a.Clear();

The following example demonstrates how to use Queues.

Code Example: Queue
Start example

using System;
using System.Collections;

namespace Client.Chapter_3___Structs__Enums__Arrays_and_Collections
{
      class Queues
      {
            static void Main(string[] args)
            {
                  //Creates a queue with 10 members
                  Queue a = new Queue(10);
                  int x = 0;
                  //Adds members to the queue
                  a.Enqueue(x);
                  x++;
                  a.Enqueue(x);
                  foreach (int y in a)
                  {
                        Console.WriteLine(y);
                  }
                  //Removes members from the queue
                  a.Dequeue();
                  //Removes all members from the queue
                  a.Clear();
            }
      }
}
End example

Team LiB
Previous Section Next Section