It’s important to know how the standard classes behave so that your code gets optimized, not performing unnecessary checks or making unnecessary calls.
Here are a number of issues I’ve seen time after time:
Fetching a value from the dictionary only if it exists
In the first version (bad) there are two dictionary lookups performed. It’s like walk in to a public library asking the librarian whether a certain book is in – and when the librarian comes back and says “yes, it’s in”, you ask again saying “Good, could you please get it for me?”. In real life it’s pretty obvious that this is a silly behavior, but in the computer world it’s not that apparent.
|
if (myDict.ContainsKey(key)) // First lookup. { ValueType value = myDict[key]; // Second lookup. // ... use the "value" here ... } |
|
🙁 |
In the second version (good), only one lookup is performed:
|
ValueType value; if (myDict.TryGetValue(key, out value)) { // ... use the "value" here ... } |
|
🙂 |
Accessing all the keys and values
I’ve seen many real-life cases where access to both the key and value is needed in a foreach-loop, and the iteration is performed over the Keys-properties while the value is accessed by a lookup:
|
foreach (TKey key in myDict.Keys) { TValue value = myDict[key]; // ... use the "key" and "value" here ... } |
|
🙁 |
If you want both the key and the value simultaneously it’s better to iterate over the dictionary as KeyValuePairs:
|
foreach (KeyValuePair<TKey, TValue> keyValuePair in myDict) { TKey key = keyValuePair.Key; TValue value = keyValuePair.Value; // ... use the "key" and "value" here ... } |
|
🙂 |
(Obviously; if you want only the keys you should use the Keys-property, and if you want only the values use the Values-property)
Overwriting a value
|
if (myDict.ContainsKey(key)) // First lookup. { myDict.Remove(key); // Second lookup. } myDict.Add(key, value); // Third lookup. |
|
🙁 |
There is really no need to remove a key before assigning a new value to it:
Removing a value
Once again, the following implementation leads to two lookups:
|
bool entryExists = myDict.ContainsKey(key); // First lookup. if (entryExists) { myDict.Remove(key); // Second lookup. } return entryExists; |
|
🙁 |
The Remove-method is actually very kind. It doesn’t crash if you try to remove something that is not there but returns a bool telling the result of the operation:
|
return myDict.Remove(key); |
|
🙂 |
When may my call fail?
The call… |
…fails when |
|
Never (*)
The value will be added if it’s not already in the dictionary, and it will be replaced if it does. |
|
|
|
|
When the entry “key” does not exist. |
|
|
|
|
When the entry “key” already exists. |
|
|
|
|
myDict.TryGetValue(key, out value); |
|
Never (*) |
|
|
|
|
Never (*)
(And the call returns false if the entry “key” does not exist.) |
(*) Well, you get an ArgumentNullException
if the key is null…