The Dictionary<TKey, TValue> Class

In this section, we will discuss the use of the Dictionary<TKey, TValue> class, which implements a dictionary. In the next section, we will discuss how this data structure can be implemented using a linked list. In subsequent sections, we will consider alternative implementations.

Note that the Dictionary<TKey, TValue> type has two type parameters, TKey and TValue. TKey is the type of the keys, and TValue is the type of the values (i.e., the data elements associated with the keys). Keys must always be non-null — any attempt to use a null key will result in an ArgumentNullException. A Dictionary<TKey, TValue>’s most basic public methods are:

Note

The type of the value parameter for TryGetValue is actually TValue, not TValue?. Another kind of annotation is used to indicate that this out parameter may be null only when the method returns false. Because such annotations are beyond the scope of CIS 300, we will treat this parameter as if it were simply defined as being nullable.

The above methods can be used for building and updating a Dictionary, as well as for looking up values by their keys. It is also possible to do updates and lookups using indexing. Specifically, a key may be used as an index in a Dictionary, as if the Dictionary were an array. For example, suppose that dictionary is a Dictionary<TKey, TValue>, k is a TKey, and v is a TValue. We can then do the following:

dictionary[k] = v;

This will associate the value v with the key k, as the Add method does; however, its behavior is slightly different if k already has a value associated with it. Whereas the Add method would throw an exception in this case, using the indexer will simply replace the value previously associated with k by the new value v. Thus, we use the Add method when we expect the key to be a new key for the dictionary, but we use the indexer when we want to associate the value with the key, regardless of whether the key is already in the dictionary.

Likewise, we can use the indexer to look up a key:

v = dictionary[k];

Again, the behavior is similar to the TryGetValue method, but slightly different, as there is no bool in the above statement. When using the indexer, if the key is not in the dictionary, it will throw a KeyNotFoundException. Thus, we use the indexer when we expect the key to be in the dictionary, but we use the TryGetValue method when we don’t know if the key is in the dictionary.