KeyNotFoundException: The given key was not present in the dictionary

Problem

The following exception is thrown when you try to get a value from a dictionary using a key that doesn’t exist in the dictionary:

KeyNotFoundException: ‘The given key was not present in the dictionary.’

Consider the following the example:

static void Main(string[] args) { Dictionary<string, string> storeManagerMap = new Dictionary<string, string>() { { "Detroit", "Alice" }, { "Chicago", "Bob" } }; string cityQuery = ""; while (cityQuery != "quit") { Console.Write("I want the manager for city: "); cityQuery = Console.ReadLine(); Console.WriteLine($"The manager for {cityQuery} is {storeManagerMap[cityQuery]}"); } Console.ReadKey(); }

When the user enters a city name that isn’t in the dictionary, such as “New York”, it’ll throw KeyNotFoundException.

Solution

The solution depends on one question: do you expect the key to always be in the dictionary?

Scenario 1 – The key might not exist

In this scenario, the user is supplying the key. In my example, they are supplying a city name and want to know the manager in that city.

Because the input is coming from the user, it’s possible the key might not exist in the dictionary. We can guard against that and report a meaningful error to the user instead of throwing an exception.

string manager; if(storeManagerMap.TryGetValue(cityQuery, out manager)) { Console.WriteLine($"The manager for {cityQuery} is {manager}"); } else { Console.WriteLine($"There is no store in {cityQuery}"); }

This is an example of the Try Pattern. Take a look at this interesting article on the subject.

Scenario 2 – The key must always exist

If the key must always exist in the dictionary, this means our code is attempting to access the dictionary with a known key, and KeyNotFoundException is truly unexpected. It may be appropriate to throw an exception here. But since you’re reading this article, I’m assuming you don’t want it to throw KeyNotFoundException, and you would rather deal with default values. If so, please continue forward.

This problem tends to happen if you are initially populating the dictionary from a database query (or some other external data source), and instead of a row with a null / missing value, it simply does not have the row.

Because the code is probably accessing the dictionary from several different places, you may not want to try to solve this with the TryGetValue() approach. An alternative approach is to initialize the dictionary with default values for known keys.

For example, let’s say I’m populating my dictionary in the code using the following SQL query:

SELECT c.CityName, m.Manager FROM [City] c INNER JOIN [Manager] m ON m.CityName = c.CityName

In my City table I have Detroit, Chicago, and New York. There is no manager for New York. Because this query is using an INNER JOIN, it doesn’t even return a row for New York.

CityName Manager Detroit Alice Chicago Bob

Hence, when I go to access the dictionary with the key “New York,” I’ll get KeyNotFoundException.

In order to get the default value for New York, I would need to change the query to use a LEFT JOIN instead:

SELECT c.CityName, m.Manager FROM [City] c LEFT JOIN [Manager] m ON m.CityName = c.CityName

This would return one row for every city, therefore I would have a row for “New York.”

CityName Manager Detroit Alice Chicago Bob New York NULL

Now when I’m populating the dictionary, I would see that the “New York” row has no manager, and I could default the value to whatever is appropriate. The appropriate value will depend on your specific situation. You may want to keep it null, or use the Null Object Pattern.

The key takeaway here is that if your code is attempting to use keys that must exist, then the best solution is to initialize the dictionary with all of the known keys and use default values when there is no valid value available.

Leave a Comment