KeyNotFoundException信息

时间:2011-07-03 14:31:04

标签: c# silverlight

我有一个随机抛出“KeyNotFoundException”的C#Silverlight应用程序。我不知道找不到什么钥匙。这引出了两个问题:

  1. KeyNotFoundException是否存储/公开了它试图找到的密钥?当我查看documentation时,我没有看到任何暗示此信息可用的内容。
  2. 我在一般的Application.UnhandledException事件处理程序中捕获/记录此异常。我的问题是,如果我在这里捕获事件,我可以将ExceptionObject转换为KeyNotFoundException,并且如果它在#1中被询问,它仍然会获得关键信息吗?
  3. 非常感谢你的帮助!

4 个答案:

答案 0 :(得分:5)

当字典抛出KeyNotFoundException时,它不会试图告诉您它试图找到哪个键。因此,我通常尝试在我的字典上使用扩展方法,这样如果我的程序中断,我知道它尝试查找的键。虽然知道堆栈跟踪是有帮助的,但通常是不够的,特别是如果查找发生在循环内。

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

更新/澄清

我实际上并没有调用key.ToString(),因为它可能是一种不会覆盖ToString()的类型。默认设置将打印类型名称:"MyLibrary.SomeType was not found.",这不如"{ managerId: 123, employeeId: 456} was not found."有用。

相反,我把它序列化为json,就像这样:

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

此外,我发现将特定键值放在异常消息中可能会使日志中的异常难以聚合,具体取决于您使用的工具类型。 (我正在使用一个通过外部异常的消息对错误进行分组的方法)。如果这会影响您,您可能希望将详细信息放在内部异常中:
throw new KeyNotFoundException( "key was not found", new KeyNotFoundException(serializedKey));

答案 1 :(得分:4)

KeyNotFoundException是由于当键不存在时尝试使用给定键从字典中获取值。例如:

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

您可以查看使用字典的所有地方并确定自己。一般的最佳实践是,如果您在字典中查找可能不存在的值,则使用TryGetValue。每次捕获异常是一项更昂贵的操作,并且是不必要的:

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

您可以查看他们StackTrace的{​​{1}}属性,以确定问题的确切位置。所有异常都具有KeyNotFoundException属性,因此您无需关心它在全局错误处理程序中的异常类型。例如:

StackTrace

或者,如果您想知道它是什么类型的异常:

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

答案 2 :(得分:3)

我认为找到问题的最佳方法是在Application.UnhandledException方法中记录给定异常的StackTrace。通过StackTrace,您可以找到问题的根源(方法的名称,导致异常的文件的名称和行)。这样,您就可以了解代码的错误。 总是尽可能多地记录。

答案 3 :(得分:0)

因为windows phone的silverlight不支持wsHttpBinding,所以你将服务改为basicHttpBinding并且它会起作用