Overview of .NET Framework Specialized Collections

Waqas Anwar
29 May 2009

Collections are classes that programmers use to group and manage related objects just like Arrays. However unlike Arrays collections are dynamically resizable objects which means they automatically grow and shrink as you add, insert or remove objects and you don’t need to worry about its size. In this Tutorial I will give you overview of some of the specialized collections available in System.Collections.Specialized namespace.

Microsoft .NET Framework has several collections for programmers to work with. The features they offer slightly varies from one type of collection to other but they all have one similar concept; they can add any type of .NET object and thus often force you to cast objects when you retrieve them from the collections. Microsoft added a new namespace in .NET Framework 2.0 called System.Collections.Specialized that includes many collections to work with specific type of data.

StringCollection class

The most common type of object you need to store in a collection is string. .NET Framework supports a specialized class called StringCollection that is strongly typed to store only strings. It is dynamically resizable list and offer similar functionality as ArrayList class. Following code snippet shows you how you can create and use StringCollection.
StringCollection sc = new StringCollection();

// sc.Add(50);   Error: only strings can be added
When you are iterating StringCollection you can use string type in the foreach loop because this is the only type stored in collection:
foreach (string item in sc)

You also don’t need to cast the element when you are retrieving it from the collection.
string firstElement = sc[0];
StringDictionary class

The StringDictionary class is a strongly typed version of the dictionary collections available in System.Collection namespace. You can use it just like Hashtable with only one difference that both keys and values must be strings.
StringDictionary sd = new StringDictionary();

sd.Add("1", "Italy");
sd.Add("2", "Spain");
sd.Add("3", "France");
sd.Add("4", "Brazil");

// Iterate Keys
foreach (string key in sd.Keys)

// Iterate Values
foreach (string value in sd.Values)

// Iterate both Keys and Values
foreach (DictionaryEntry item in sd)
   Console.WriteLine(item.Key + " : " + item.Value);

ListDictionary class

.NET developers normally use Hashtable to store key/value pairs together. This is the most common type of dictionary collection used in development but it has one issue that it requires a bit of overhead and if you want to store only few elements this overhead can cause performance issues. This is where another specialized .NET Framework class ListDictionary comes in. ListDictionary is very efficient for small collections of items (less than ten elements) because it is implemented as a simple array of items underneath. It has similar interface as Hashtable and can be used as replacement.
ListDictionary ld = new ListDictionary();

ld.Add("1", "Italy");
ld.Add("2", "Spain");
ld.Add("3", "France");
ld.Add("4", "Brazil");

foreach (DictionaryEntry item in ld)
   Console.WriteLine(item.Key + " : " + item.Value);

HybridDictionary class

You can use ListDictionary when you have small collection of items to store for increasing application performance and you can use Hashtable when you have large number of items to store. What if you do not know how many items your program has to store in collection. HybridDictionary helps you under these circumstances because it implements ListDictionary and Hashtable both internally and automatically switches between those two based on the number of items you store. Using HybridDictionary is similar as other Dictionary based classes in .NET Framework.
HybridDictionary hd = new HybridDictionary();

hd.Add("1", "Italy");
hd.Add("2", "Spain");
hd.Add("3", "France");
hd.Add("4", "Brazil");

foreach (DictionaryEntry item in hd)
   Console.WriteLine(item.Key + " : " + item.Value);

OrderedDictionary class

When you use Hashtable class, you do not have access to its elements by index no and if you try to iterate items using enumerator, the items are ordered based on their hash value and not in the order you need. When you need both the power of a collection, and the simple access of a numeric index, the OrderedDictionary is the collection of choice. It not only gives you a very fast dictionary but also keep your items in order. Using this class, you can perform specific actions at a numeric index in the collection, or you can use the Dictionary Entry style of looping over the collection.
OrderedDictionary od = new OrderedDictionary();

od.Add("1", "Italy");
od.Add("2", "Spain");
od.Add("3", "France");
od.Add("4", "Brazil");

// Iterate items using index no (array style)
for (int i = 0; i < od.Count; i++)

// Iterate items using DictionaryEntry (dictionary style)
foreach (DictionaryEntry item in od)
   Console.WriteLine(item.Key + " : " + item.Value);
Above you can see I used two different methods to iterate over my collection. In the first example, I used a for loop and a numeric index to retrieve each item stored in the collection. In the second loop, you can see code similar to other dictionaries I covered above using a DictionaryEntry object to iterate over the collection. When going over a large collection, reading the OrderedDictionary using the first example, the numeric index, is always going to be faster than using the dictionary style method.

NameValueCollection class

NameValueCollection is another specialized dictionary in the Framework. It only adds strings as keys and values just as StringDictionary class. However there is one difference, it allows you to add multiple values with the single key and those values can be retrieved by index as well as key. In the following code I am using Add method of NameValueCollection class to add multiple values with same key. If you want to retrieve all values associated with any particular key you can use GetValues() method as shown below.          NameValueCollection nvc = new NameValueCollection();

nvc.Add("System", "Systen.String");
nvc.Add("System", "Systen.Int32");
nvc.Add("System", "Systen.Decimal");
nvc.Add("System", "Systen.Boolean");

nvc.Add("System.IO", "Systen.IO.File");
nvc.Add("System.IO", "Systen.IO.FileInfo");
nvc.Add("System.IO", "Systen.IO.DirectoryInfo");
nvc.Add("System.IO", "Systen.IO.DriveInfo");

nvc.Add("System.Data", "Systen.Data.DataTable");
nvc.Add("System.Data", "Systen.Data.DataSet");
nvc.Add("System.Data", "Systen.Data.DataRow");

if (nvc.HasKeys())
   foreach (string key in nvc.Keys)

      foreach (string value in nvc.GetValues(key))