Dictionary with Multiple Keys
The dictionaries available with the .NET
Framework only support one value per key. You cannot add multiple
values to the same key. However, you can create a custom dictionary
that is based on Dictionary<TKey,
TValue> and uses a list as value.
The class MultiDictionary
<TKey, TValue> implements the interface IDictionary<TKey, TValue>. Contained in this class is the generic
Dictionary class that has the same key
TKey from the outer class, but the value
is defined as type List<TValue>.
Every key maps to a value of type List<TValue>.
MultiDictionary<TKey,
TValue> requires the implementation of the interface
IDictionary<TKey, TValue> methods Add(),
ContainsKey(), Remove(), TryGetValue();
the properties Keys and Values; and the indexer.
The implementation of the Add() method first determines if the key has already
been added to the dictionary with TryGetValue(). If the key is already in the
dictionary, the new value is added to the list that is returned
from TryGetValue(). Otherwise, a new
list is created, the value is added to the list, and the key
together with the list is added to the dictionary.
The methods ContainsKey(), Remove(),
and the property Keys can be implemented
by forwarding the request to the contained dictionary:
The property Values must
convert the internal values of type List<TValue> to type TValue. After the while
loop is completed, the list named values
contains all values from all the lists that are stored as values in
the contained dictionary. The while loop
uses the enumerator from the variable dict to iterate through all keys to add all items to
the list that is returned.
The indexer and the TryGetValue method are not supported with
MultiDictionary, because a key can be
associated with more than one value, so a single value cannot be
returned:
With this class, it’s not useful to have an indexer
of type TValue, but it’s useful to have
an indexer of type IList<TValue>:
The interface IDictionary<TKey, TValue> is derived from
ICollection<KeyValuePair<TKey,
TValue>>, so the methods
Add(), Clear(), Contains(),
CopyTo(), and Remove(), and the properties Count and IsReadOnly must
be implemented as well.
The Add() method with
the argument of type KeyValuePair<TKey,
TValue> just needs to invoke the Add() method, where TKey
and TValue are passed separately. The
Clear() method invokes the Clear() on the contained dictionary. Contains() returns false
if the key specified does not exist. If the key exists,
list.Contains() determines if the value
is in the list and returns the result. CopyTo() copies all items to an array. The property
Count returns the number of all
values.
IDictionary<TKey, TValue> is also derived
from IEnumerable<KeyValuePair<TKey,
TValue>>, so the method GetEnumerator() must be implemented. Here, the
yield return statement is of practical
use.
The MultiDictionary<TKey,
TValue> can be created like a normal dictionary, but here
it’s possible to use the same key multiple times. In this case, the
country is used as the key and Racer as
value. Two racers from Australia and two racers from the United
Kingdom are added to the dictionary. The indexer of this dictionary
returns a list that is iterated through with a foreach loop.
The output shows the racers from Australia: