Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KeyNotFoundException info

Tags:

c#

silverlight

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:

  1. Does a 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.
  2. I am catching/logging this exception in a general Application.UnhandledException event handler. My question is, if I catch the event here, can I convert the ExceptionObject to a KeyNotFoundException and still get the key information if its exposed as asked in #1?

Thank you so much for your help!

like image 246
user208662 Avatar asked Jul 03 '11 14:07

user208662


People also ask

How do you handle KeyNotFoundException?

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.

What does the given key was not present in the dictionary mean?

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.


1 Answers

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));

like image 152
dan Avatar answered Sep 27 '22 23:09

dan