Specialized Collections

Now that you have covered all of the standard collections, you'll take a look at a few of the more commonly used specialized collections provided by the .NET Framework class library. Unlike the standard set of collections that I discussed previously, these specialized collections require the referencing of the system.dll assembly and use the System::Collections::Specialized namespace.

 #using <system.dll> using System::Collections::Specialized; 


If you require quick access to a short list of elements, a ListDictionary might just be what you need. It has very little overhead. It is just a singular link list, which makes it very fast if you plan on restricting the number of data elements to ten or less. When you plan on having more than ten elements, it is probably better to use a Hashtable.

In fact, the .NET Framework class library provides a specialized collection called the HybridDictionary that starts off as a ListDictionary when the number of entries is small and automatically changes to a Hashtable when the number of elements increases.

The ListDictionary has few methods, all of which you learned about earlier in this chapter. A feature that the ListDictionary shares with the Hashtable (and the SortedList), which you haven't covered already, is the capability to add key/value pairs using the Item indexed property. As you might expect, when the key passes, the value gets changed because the indexed property already exists.


What you might not expect is that if the key is unique, then the key/value pair is added.


Add() works when adding a unique key only. Duplicate keys passed to the Add() method throw an ArgumentException instead of replacing the value.

Listing 7-6 shows the ListDictionary in action and demonstrates the functionality described previously.

Listing 7-6: Working with ListDictionary

start example
 #using <mscorlib.dll> #using <system.dll> using namespace System; using System::Collections::Specialized; Int32 main(void) {     ListDictionary *ldict = new ListDictionary();     ldict->Add(S"A", S"First");     ldict->Add(S"B", S"Second");     ldict->Add(S"C", S"Third");     ldict->Item[S"D"] = S"Fourth";     try {         ldict->Add(S"C", S"Third Replaced");     }     catch (ArgumentException *e)     {         Console::WriteLine(S"ldict->Add(S\"C\", S\"Third Replaced\");");         Console::WriteLine(S"Throws exception: {0}", e->Message);     }     ldict->Item[S"B"] = S"Second Replaced";     Console::WriteLine(S"\nEnumerate");     IEnumerator *keys = ldict->Keys->GetEnumerator();     IEnumerator *vals = ldict->Values->GetEnumerator();     while ( keys->MoveNext() && vals->MoveNext())     {         Console::WriteLine(S"{0}\t\t{1}", keys->Current, vals->Current);     }     Console::WriteLine(S"\n");     return 0; } 
end example

Figure 7-6 shows the results of the ListDict.exe program.

click to expand
Figure 7-6: Results of ListDict.exe


When you plan on maintaining many strings, it might be more advantageous to use a StringCollection than of any of the other collection types, as a StringCollection is optimized to handle strings. A StringCollection resembles a simplified ArrayList in many ways, except that it lacks a few of its methods and uses the StringEnumerator instead of the IEnumerator.

Listing 7-7 shows the StringCollection in action. As you can see, it has many of the same methods of an ArrayList and is strongly typed to strings.

Listing 7-7: Working with StringCollection

start example
 #using <mscorlib.dll> #using <system.dll> using namespace System; using System::Collections::Specialized; Int32 main(void) {     StringCollection &strcol = *new StringCollection();     strcol.Add(S"The first String");     String *tmpstr[] = {S"Third", S"Fourth" };     strcol.AddRange(tmpstr);     strcol.Insert(1, S"Second");     strcol.Item[0] = S"First";     StringEnumerator *strenum = strcol.GetEnumerator();     while ( strenum->MoveNext())     {         Console::WriteLine(strenum->Current);     }     Console::WriteLine(S"");     return 0; } 
end example

Figure 7-7 shows the results of the StringColl.exe program.

click to expand
Figure 7-7: Results of StringColl.exe


The StringDictionary sounds impressive, don't you think? It's really just a Hashtable strongly typed and optimized for strings. There's nothing new here, other than pretty well all methods expect the String type instead of the Object type.

Listing 7-8 shows the StringDictionary in action. This example shows one of the many ways of displaying the StringDictionary in alphabetical order, as a StringDictionary does not sort its entries. If you recall, a Hashtable works by simply analyzing the key to find its value, and no sorting occurs. In the example, you get a copy of all the keys and place them into an ArrayList. Then, you use the ArrayList's built-in Sort() method.

Listing 7-8: Working with StringDictionary

start example
 #using <mscorlib.dll> #using <system.dll> using namespace System; using System::Collections::Specialized; Int32 main(void) {     StringDictionary &strdict = *new StringDictionary();     strdict.Add(S"Dog", S"Four leg, hydrant loving, barking, mammal");     strdict.Add(S"Frog", S"Green, jumping, croaking, amphibian");     strdict.Item[S"Crocodile"] = S"Ugly, boot origin, snapping, reptile";     ArrayList *alist = new ArrayList();     alist->AddRange(strdict.Keys);     alist->Sort();     for (Int32 i = 0; i < alist->Count; i++)     {         Console::WriteLine(S"{0,10}:\t{1}", alist->Item[i],             strdict.Item[dynamic_cast<String*>(alist->Item[i])]);     }     Console::WriteLine(S"");     return 0; } 
end example

Figure 7-8 shows the results of the StringDict.exe program.

click to expand
Figure 7-8: Results of StringDict.exe


Let's finish off the chapter with one final collection type: NameValueCollection. This collection is similar in many ways to the StringDictionary. It uses a Hashtable internally and is optimized for handling string. Where it differs is in its ability to have multiple values for a single key.

You can add a key/value pair to a NameValueCollection using the Add() or Set() method or the indexed property Item. However, only the Add() method allows multiple values to be assigned to a single key:

 nvCol.Set(S"Flower", S"Rose"); nvCol.Add(S"Animal", S"Dog"); nvCol.Item[S"Fruit"] = S"Plum"; 

You can update the value of a key using either the Item property or the Set() method, but in both cases only a single value can be assigned to a key.


The indexed property Item and the Set() method will overwrite a key with multiple values with a single value. In other words, you will lose all values assigned to the key and they will be replaced with the new single value.

To get all the keys in the collection, you use the AllKeys property. This property returns an array, which has been cached for better performance and which is automatically refreshed when the collection changes.

 String *keys[] = nvCol.AllKeys; 

There are two different ways of getting the values using a key: either as an array of strings using the GetValues() method or as a comma-delimited list using the Get() method.

 String *vals[] = nvCol.GetValues(S"Flower"); String *vals = nvCol.Get(S"Flower"); 

It is also possible to manipulate the collection using indexes. To get a key at a specific index, use the GetKey() method.

 String *key = nvCol.GetKey(1); 

To get the values at a specific index, you use the Item property, but this time as an array property. Using Item this way returns a comma-delimited list of values.

 String *vals = nvCol.Item[3]; 

You remove a specific key and all its values from the collection by passing the index of the key you want to remove into the Remove() method.

Listing 7-9 shows the NameValueCollection in action.

Listing 7-9: Working with NameValueCollection

start example
 #using <mscorlib.dll> #using <system.dll> using namespace System; using namespace System::Collections::Specialized; Int32 main(void) {     NameValueCollection &nvCol = *new NameValueCollection();     nvCol.Add(0, S"void");     nvCol.Set(S"Flower", S"Rose");     nvCol.Add(S"Animal", S"Dog");     nvCol.Add(S"Animal", S"Cat");     nvCol.Add(S"Animal", S"Cow");     nvCol.Add(S"Fruit", S"Apple");     nvCol.Add(S"Fruit", S"Pear");     nvCol.Add(S"Fruit", S"Peach");     String *keys[] = nvCol.AllKeys;     Console::WriteLine(S"Key\t\tValues");     for (Int32 i = 0; i < keys->Count; i++)     {         String *vals[] = nvCol.GetValues(keys[i]);         Console::WriteLine(S"{0}:\t\t{1}", keys[i], vals[0]);         for (Int32 j = 1; j < vals.Count; j++)         {             Console::WriteLine(S"\t\t{0}", vals[j]);         }     }     Console::WriteLine(S"--- Index Lookups ---");     Console::WriteLine(S"Key @[1]:\t{0}", nvCol.GetKey(1));     Console::WriteLine(S"Values @[3]:\t{0}", nvCol.Item[3]);     nvCol.Remove(0);     nvCol.Item[S"Fruit"] = S"Plum";     nvCol.Set(S"Animal", S"Deer");     nvCol.Add(S"Animal", S"Ape");     keys = nvCol.AllKeys;     Console::WriteLine(S"------ Updated ----");     for (Int32 i = 0; i < keys->Count; i++)     {         Console::WriteLine(S"{0}:\t\t{1}", keys[i], nvCol.Get(keys[i]));     }     return 0; } 
end example

Figure 7-9 shows the results of the NameValue.exe program.

click to expand
Figure 7-9: Results of NameValue.exe

Managed C++ and. NET Development
Managed C++ and .NET Development: Visual Studio .NET 2003 Edition
ISBN: 1590590333
EAN: 2147483647
Year: 2005
Pages: 169

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