Using Lists and Collections in .NET
Welcome to the next installment of the .NET Nuts & Bolts column. This article outlines the concept of lists and collections in .NET and the current native support that the .NET Framework provides. It touches on a couple of the more common classes in the System.Collections namespace and finishes by exploring why this topic is especially important with the planned inclusion of generics in version 2.0 of the .NET Framework.
System.Collections Namespace
The System.Collections namespace contains a number of different interfaces and classes that define various types of objects, such as lists, hashtables, and dictionaries. Each class has the following attributes:
• It is a container of sorts that implements different forms of lists or arrays.
• It has a different implementation that stores or relates the items contained within differently.
• It has its own scenario where it is applied.
This article focuses on the ArrayList, Hashtable, and CollectionBase, which are some of the more commonly utilized classes.
ArrayList
The array list, as its name implies, is a type very similar to a traditional array. It is simply an improvement in the usability of traditional arrays. Most languages require you to size arrays when you create them. That size is fixed for the lifetime of the array. An ArrayList is an array wrapper that allows the size to dynamically increase as needed. You do not need to know the array's size at the time when you create the ArrayList, and the array is not limited in size.
ArrayLists are designed to hold objects, which means the contents of the ArrayList can be anything you want because everything derives from System.Object. It has member methods to control adding, clearing, removing, searching, sorting, and trimming to a specific size. The ArrayList supports adding new items into the list through either an Add method that simply adds to the end of the list or an Insert method that adds an item at a specific location.
As you add objects to the ArrayList, it compares the number of elements to the ArrayList's current capacity (default of 16). If the addition of the new item will exceed the current capacity, the ArrayList's internal array automatically doubles in size and the current contents are copied into the newly sized internal array. This is important because it has performance implications for your applications. The time it takes to create a new array of doubled size and then traverse the internal array to copy all of the contents into the new internal array is performance overhead. Just because the ArrayList is designed to allow for a dynamic size, you shouldn't ignore sizing it if you know a relative size you will need. It performs best if you specify a size at the time you create the ArrayList.
ArrayList Sample Code
The following sample code is from a console application (In the interest of brevity, only the relevant code is listed because the majority of the code in the application was automatically generated when the project was created.):
/*
* Sample class to add to lists.
*/
private class TestItem
{
private int _ItemValue = 0;
public int ItemValue
{
get { return this._ItemValue; }
set { this._ItemValue = value; }
}
public TestItem(int itemValue)
{
this.ItemValue = itemValue;
}
}
/*
* Code to demonstrate using the ArrayList
*/
ArrayList aList = new ArrayList();
// Show the default capacity
Console.WriteLine("Default ArrayList capacity: "
+aList.Capacity.ToString());
// Add some numbers to the list
for( int i = 0; i < 20; i++ )
{
aList.Add(new TestItem(i));
}
// Retrieve the enumerator and use it to loop the list
IEnumerator listEnumerator = aList.GetEnumerator();
while( listEnumerator.MoveNext() )
{
Console.WriteLine("{0}", ((TestItem)
(listEnumerator.Current)).ItemValue);
}
// Wait so you can read the output
System.Console.ReadLine();
Notice how the value in the ArrayList must be cast at the time it is pulled out of the ArrayList. This generally isn't necessary for basic types (such as int, string, and so forth), but it is for all others.
Hashtable
A Hashtable represents a collection of key-and-value pairs. Whereas arrays are organized according to a sequential numbered index, Hashtables use a different internal storage algorithm based on a hash of the keys provided. Each storage location is often referred to as a bucket. Each key hashes to a unique bucket. Similar to the ArrayList, objects of any desired type can be stored in the Hashtable. It has member methods to control adding, clearing, removing, searching, and safely checking whether a key or value is already contained within the Hashtable.
Hashtable Sample Code
One of the common uses for Hashtables is enabling a specified identifier to quickly retrieve items. Examples could be phone numbers, Social Security numbers, database identity columns, and so on. The following sample code demonstrates the use of a Hashtable. It simply uses a random number generator to create identities, checks to see whether they exist, and, if not, adds them to the Hashtable:
/*
* Code to demonstrate using the Hashtable
*/
Hashtable hash = new Hashtable();
int key = 0;
Random randomKey = new Random(1);
// Add some numbers to the list
for( int i = 0; i < 20; i++ )
{
key = randomKey.Next();
if( !hash.ContainsKey( key ) )
{
hash.Add(key, new TestItem(i));
}
else
{
Console.WriteLine("Key {0} already exists.", key);
}
}
// Display the contents of the Hashtable
System.Console.WriteLine("Number of Items: " + hash.Count);
IDictionaryEnumerator listEnumerator = hash.GetEnumerator();
while ( listEnumerator.MoveNext() )
{
Console.WriteLine("\t{0}:\t{1}",
listEnumerator.Key,
((TestItem)(listEnumerator.Value)).ItemValue);
}
// Wait so you can read the output
System.Console.ReadLine();
The random number generator likely won't produce any clashes with such a short loop, but it demonstrates the concept. The sample code assumes reuse of the TestItem class and as with the previous example, the code is limited to what is not generated by default in a console application.
CollectionBase
A CollectionBase is similar to ArrayLists and Hashtables in that it is a list. However, a CollectionBase is an abstract class that allows you to define type-specific lists. For example, if you wanted a list of just TestItem from the previous sample code, you would use the CollectionBase as the base class for your object and then create the appropriate methods or override the desired functionality.
CollectionBase Sample Code
The following sample defines a list that has TestItem as the specific type. It includes sample methods for add/remove functionality:
/*
* Sample collection that is specific to TestItem type.
*/
private class TestItemCollection : CollectionBase
{
public TestItem this[ int index ]
{
get { return( (TestItem) List[index] ); }
set { List[index] = value; }
}
public int Add( TestItem itemValue )
{
return( List.Add( itemValue ) );
}
public void Remove( TestItem itemValue )
{
List.Remove( itemValue );
}
}
/*
* Code to demonstrate using our TestItemCollection
*/
TestItemCollection testCollection = new TestItemCollection();
// Add some numbers to the list
for( int i = 0; i < 20; i++ )
{
testCollection.Add(new TestItem(i));
}
IEnumerator listEnumerator = testCollection.GetEnumerator();
while( listEnumerator.MoveNext() )
{
Console.WriteLine("{0}", ((TestItem)
(listEnumerator.Current)).ItemValue);
}
// Wait so you can read the output
System.Console.ReadLine();
Welcome to the next installment of the .NET Nuts & Bolts column. This article outlines the concept of lists and collections in .NET and the current native support that the .NET Framework provides. It touches on a couple of the more common classes in the System.Collections namespace and finishes by exploring why this topic is especially important with the planned inclusion of generics in version 2.0 of the .NET Framework.
System.Collections Namespace
The System.Collections namespace contains a number of different interfaces and classes that define various types of objects, such as lists, hashtables, and dictionaries. Each class has the following attributes:
• It is a container of sorts that implements different forms of lists or arrays.
• It has a different implementation that stores or relates the items contained within differently.
• It has its own scenario where it is applied.
This article focuses on the ArrayList, Hashtable, and CollectionBase, which are some of the more commonly utilized classes.
ArrayList
The array list, as its name implies, is a type very similar to a traditional array. It is simply an improvement in the usability of traditional arrays. Most languages require you to size arrays when you create them. That size is fixed for the lifetime of the array. An ArrayList is an array wrapper that allows the size to dynamically increase as needed. You do not need to know the array's size at the time when you create the ArrayList, and the array is not limited in size.
ArrayLists are designed to hold objects, which means the contents of the ArrayList can be anything you want because everything derives from System.Object. It has member methods to control adding, clearing, removing, searching, sorting, and trimming to a specific size. The ArrayList supports adding new items into the list through either an Add method that simply adds to the end of the list or an Insert method that adds an item at a specific location.
As you add objects to the ArrayList, it compares the number of elements to the ArrayList's current capacity (default of 16). If the addition of the new item will exceed the current capacity, the ArrayList's internal array automatically doubles in size and the current contents are copied into the newly sized internal array. This is important because it has performance implications for your applications. The time it takes to create a new array of doubled size and then traverse the internal array to copy all of the contents into the new internal array is performance overhead. Just because the ArrayList is designed to allow for a dynamic size, you shouldn't ignore sizing it if you know a relative size you will need. It performs best if you specify a size at the time you create the ArrayList.
ArrayList Sample Code
The following sample code is from a console application (In the interest of brevity, only the relevant code is listed because the majority of the code in the application was automatically generated when the project was created.):
/*
* Sample class to add to lists.
*/
private class TestItem
{
private int _ItemValue = 0;
public int ItemValue
{
get { return this._ItemValue; }
set { this._ItemValue = value; }
}
public TestItem(int itemValue)
{
this.ItemValue = itemValue;
}
}
/*
* Code to demonstrate using the ArrayList
*/
ArrayList aList = new ArrayList();
// Show the default capacity
Console.WriteLine("Default ArrayList capacity: "
+aList.Capacity.ToString());
// Add some numbers to the list
for( int i = 0; i < 20; i++ )
{
aList.Add(new TestItem(i));
}
// Retrieve the enumerator and use it to loop the list
IEnumerator listEnumerator = aList.GetEnumerator();
while( listEnumerator.MoveNext() )
{
Console.WriteLine("{0}", ((TestItem)
(listEnumerator.Current)).ItemValue);
}
// Wait so you can read the output
System.Console.ReadLine();
Notice how the value in the ArrayList must be cast at the time it is pulled out of the ArrayList. This generally isn't necessary for basic types (such as int, string, and so forth), but it is for all others.
Hashtable
A Hashtable represents a collection of key-and-value pairs. Whereas arrays are organized according to a sequential numbered index, Hashtables use a different internal storage algorithm based on a hash of the keys provided. Each storage location is often referred to as a bucket. Each key hashes to a unique bucket. Similar to the ArrayList, objects of any desired type can be stored in the Hashtable. It has member methods to control adding, clearing, removing, searching, and safely checking whether a key or value is already contained within the Hashtable.
Hashtable Sample Code
One of the common uses for Hashtables is enabling a specified identifier to quickly retrieve items. Examples could be phone numbers, Social Security numbers, database identity columns, and so on. The following sample code demonstrates the use of a Hashtable. It simply uses a random number generator to create identities, checks to see whether they exist, and, if not, adds them to the Hashtable:
/*
* Code to demonstrate using the Hashtable
*/
Hashtable hash = new Hashtable();
int key = 0;
Random randomKey = new Random(1);
// Add some numbers to the list
for( int i = 0; i < 20; i++ )
{
key = randomKey.Next();
if( !hash.ContainsKey( key ) )
{
hash.Add(key, new TestItem(i));
}
else
{
Console.WriteLine("Key {0} already exists.", key);
}
}
// Display the contents of the Hashtable
System.Console.WriteLine("Number of Items: " + hash.Count);
IDictionaryEnumerator listEnumerator = hash.GetEnumerator();
while ( listEnumerator.MoveNext() )
{
Console.WriteLine("\t{0}:\t{1}",
listEnumerator.Key,
((TestItem)(listEnumerator.Value)).ItemValue);
}
// Wait so you can read the output
System.Console.ReadLine();
The random number generator likely won't produce any clashes with such a short loop, but it demonstrates the concept. The sample code assumes reuse of the TestItem class and as with the previous example, the code is limited to what is not generated by default in a console application.
CollectionBase
A CollectionBase is similar to ArrayLists and Hashtables in that it is a list. However, a CollectionBase is an abstract class that allows you to define type-specific lists. For example, if you wanted a list of just TestItem from the previous sample code, you would use the CollectionBase as the base class for your object and then create the appropriate methods or override the desired functionality.
CollectionBase Sample Code
The following sample defines a list that has TestItem as the specific type. It includes sample methods for add/remove functionality:
/*
* Sample collection that is specific to TestItem type.
*/
private class TestItemCollection : CollectionBase
{
public TestItem this[ int index ]
{
get { return( (TestItem) List[index] ); }
set { List[index] = value; }
}
public int Add( TestItem itemValue )
{
return( List.Add( itemValue ) );
}
public void Remove( TestItem itemValue )
{
List.Remove( itemValue );
}
}
/*
* Code to demonstrate using our TestItemCollection
*/
TestItemCollection testCollection = new TestItemCollection();
// Add some numbers to the list
for( int i = 0; i < 20; i++ )
{
testCollection.Add(new TestItem(i));
}
IEnumerator listEnumerator = testCollection.GetEnumerator();
while( listEnumerator.MoveNext() )
{
Console.WriteLine("{0}", ((TestItem)
(listEnumerator.Current)).ItemValue);
}
// Wait so you can read the output
System.Console.ReadLine();
Comments
Post a Comment