I have an C# Silverlight application that is randomly throwing a "KeyNotFoundException
". I have no idea what key cannot be found. This has lead me to two questions:
KeyNotFoundException
store/expose what key it tried to find? When I looked in the documentation, I did not see anything that implied this information was available.Thank you so much for your help!
We can fix this exception by using the TryGetValue method. Note that could use ContainsKey instead of TryGetValue. But we preserve the intention of the previous code here. Important We use if-statement when testing values in the Dictionary, because there is always a possibility that the key will not exist.
The error 'The given key is not present in the dictionary' simply means that the dictionary does not have a value that corresponds to the key. So, this error would occur in the first line if InputParameters does not contain a key called "Target", or in the second line if there were no "name" in Attributes.
When a dictionary throws a KeyNotFoundException
, it makes no attempt to tell you which key it tried to find. Because of that, I usually try to use an extension method on my dictionaries so that if my program breaks, I know what key it tried to lookup. While knowing the stack trace is helpful, it often isn't enough, especially if the lookup is happening inside a loop.
public static TValue GetOrThrow<TKey,TValue>(this IDictionary<TKey,TValue> d, TKey key)
{
try
{
return d[key];
}
catch(KeyNotFoundException ex)
{
throw new KeyNotFoundException(key.ToString()
+ " was not found in the dictionary");
}
}
update / clarifications
I don't actually call key.ToString()
because it might be a type which doesn't override ToString()
. The default would print the type name: "MyLibrary.SomeType was not found."
, which is not as helpful as "{ managerId: 123, employeeId: 456} was not found."
.
So instead, I serialize it to json, like so:
var serializedKey = Newtonsoft.Json.JsonConvert.SerializeObject(
key,
new JsonSerializerSettings
{
//make it easy for humans to read
Formatting = Formatting.Indented,
//don't break on loops...that would cause a new error that hides the KeyNotFound!
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
Additionally, I've found that putting the specific key value in the exception message can make it hard to aggregate exceptions in logs, depending on what kind of tooling you use. (I'm working with one that groups errors by the outer exception's message). If this affects you, you might want to put the details in an inner exception:throw new KeyNotFoundException(
"key was not found",
new KeyNotFoundException(serializedKey));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With