Dot Net Perls

Dictionary Lookup Methods - C#

by Sam Allen

Problem

You want to look up values at certain keys in your Dictionary. Compare two common methods for lookup: ContainsKey and TryGetValue. Develop exception-free and very fast code for looking up keys and their values in your Dictionaries.

Solution: C# Dictionary

The Dictionary generic collection in C# is excellent, but sometimes developers misuse it. For performance, you must minimize key lookups. Whenever you access Dictionary with a key, the framework computes a 'hash' from that value.

Example: look up keys in Dictionary

Here are two lookup methods you absolutely must know to use Dictionary effectively. ContainsKey simply returns a bool indicating whether the key exists. Then, you can access the Dictionary again to get the value. The next is TryGetValue, and it does both tasks at once.

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary<string, bool> d = new Dictionary<string, bool>();
        d.Add("cat", true);
        d.Add("dog", false);
        d.Add("sprout", true);

        // A.
        // We could use ContainsKey.
        if (d.ContainsKey("dog"))
        {
            // Will be 'False'
            bool result = d["dog"];
            Console.WriteLine(result);
        }

        // B.
        // Or we could use TryGetValue.
        bool value;
        if (d.TryGetValue("dog", out value))
        {
            // Will be 'False'
            bool result = value;
            Console.WriteLine(result);
        }
    }
}

Question: is this important?

Yes, it often is. Hashtables improve the performance of finding an entry by using a simpler lookup algorithm. TryGetValue can halve the amount of work for your hashtable. Normally Dictionaries are used in performance-sensitive code.

Question: how fast is it?

TryGetValue is considerably faster than ContainsKey. What I did to compare the methods was develop one method that uses ContainsKey, as above, and another that uses TryGetValue. The methods combine a lookup and an Add to the values in the Dictionary.

ContainsKey versionTryGetValue version
// // Add value to key List. // if (_dict.ContainsKey(key)) { _dict[key].Add(value); } else { List<string> list = new List<string>(); list.Add(value); _dict.Add(key, list); }// // Add the value the list at "key". // List<string> list; if (_dict.TryGetValue(key, out list)) { list.Add(value); } else { list = new List<string>(); list.Add(value); _dict.Add(key, list); }

ContainsKey is first. The second method above shows TryGetValue. Look carefully at how it calls Add on the List value. The first method doesn't do that. It uses ContainsKey and looks up the value again.

Benchmark details. My testing used a small number of keys and values, and built up the Dictionary quite heavily. This stressed the code path where TryGetValue avoids a lookup.

Information: don't use TryGetValue always

An anonymous reader sent helpful benchmarks of how TryGetValue can slow down Dictionary accesses when it is used unnecessarily. I learned here that you should only use TryGetValue when you need to get the value.

This is likely simply due to the overhead of the more complex function signature with TryGetValue. However, I recommend using ContainsKey when you only need to know if a value exists.

Discussion: TryGetValue on Dictionary

Dictionary is enormously powerful and useful for C# developers. Eliminate duplicate lookups with TryGetValue. Always check to make sure a key exists before trying to access it with the square brackets. Finally, go read a real book if Dictionary isn't treating you right.

For a comparison of how the algorithmic complexity of Dictionary fares versus an array, see my article on the subject. [Dictionary vs. List]

Dot Net Perls
About
Sitemap
Source code
RSS
Dictionary
Dictionary Keys and Values
Dictionary Lookup Methods
Sort Dictionary Values
Dictionary vs. List Lookup Time
ToDictionary Use
Recent
Pi
NGEN Installer Class
List Element Equality
DateTime Tips and Tricks
Remove HTML Tags From String
© 2008 Sam Allen. All rights reserved.