KeyNotFoundException info

最后都变了- 提交于 2019-12-23 10:54:12

问题


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!


回答1:


A KeyNotFoundException is caused by trying to get the value out of a Dictionary with a given key when they key is not present. For example:

var dictionary = new Dictionary<string, string>();
var val = dictionary["mykey"];

You can look at all of the places where a dictionary is being used and determine yourself. A general best practice for that is if you are looking for a value in a dictionary that might not be present would be to use TryGetValue. Catching the exception every time is a more expensive operation and is unnecessary:

string val;
if(dictionary.TryGetValue("mykey", out val))
{
     //The key was found. The value is in val.
}
else
{
    //The key was not present.
}

You can look at the StackTrace property of they KeyNotFoundException to determine exactly where the problem is happening. All exceptions have the StackTrace property, so you don't need to care what type of exception it was in your global error handler. For example:

private void Application_UnhandledException(object sender, 
        ApplicationUnhandledExceptionEventArgs e)
    {
         var stackTrace = e.ExceptionObject.StackTrace;
         //Log the stackTrace somewhere.
    }

Or, if you want to be able to tell what type of Exception it is:

private void Application_UnhandledException(object sender, 
        ApplicationUnhandledExceptionEventArgs e)
    {
         if (e.ExceptionObject is KeyNotFoundException)
         {
             //This was a KeyNotFoundException
         }
    }



回答2:


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




回答3:


I think the best way to find the problem is to log the StackTrace of the given exception in Application.UnhandledException method. By StackTrace, you can find the origin of the problem (the name of the method, the name and line of the file causing the exception). This way, you can understand what's wrong with your code. Always try to log as much as you can.




回答4:


It is because silverlight for windows phone doesn't support wsHttpBinding, so you change you service to basicHttpBinding and it will work



来源:https://stackoverflow.com/questions/6563491/keynotfoundexception-info

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!