KeyNotFoundException信息
我有一个C#Silverlight应用程序,它随机抛出一个“ KeyNotFoundException
”。 我不知道找不到什么钥匙。 这引出了两个问题:
-
KeyNotFoundException
是否存储/公开它试图找到的键? 当我查看文档时 ,我没有看到任何暗示此信息可用的内容。 - 我在一般的Application.UnhandledException事件处理程序中捕获/记录此exception。 我的问题是,如果我在这里捕获事件,我可以将ExceptionObject转换为KeyNotFoundException,并且如果它在#1中被询问,它仍然会获得关键信息吗?
非常感谢你的帮助!
KeyNotFoundException
是由于当键不存在时尝试使用给定键从字典中获取值而引起的。 例如:
var dictionary = new Dictionary(); var val = dictionary["mykey"];
您可以查看使用字典的所有位置并确定自己。 一般的最佳实践是,如果您在字典中查找可能不存在的值,则使用TryGetValue
。 每次捕获exception都是一项更昂贵的操作,并且是不必要的:
string val; if(dictionary.TryGetValue("mykey", out val)) { //The key was found. The value is in val. } else { //The key was not present. }
您可以查看KeyNotFoundException
的StackTrace
属性,以确定问题的确切位置。 所有exception都具有StackTrace
属性,因此您无需关心它在全局error handling程序中的exception类型。 例如:
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) { var stackTrace = e.ExceptionObject.StackTrace; //Log the stackTrace somewhere. }
或者,如果您希望能够告诉它是什么类型的exception:
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) { if (e.ExceptionObject is KeyNotFoundException) { //This was a KeyNotFoundException } }
当字典抛出KeyNotFoundException
,它不会尝试告诉您它试图找到哪个键。 因此,我经常尝试在我的词典上使用扩展方法,这样如果我的程序中断,我知道它试图查找的键。 虽然知道堆栈跟踪是有用的,但通常是不够的,特别是如果查找发生在循环内。
public static TValue GetOrThrow(this IDictionary 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."
那么有用"{ 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 });
此外,我发现将特定键值放在exception消息中会使得很难在日志中聚合exception,具体取决于您使用的工具类型。 (我正在使用一个通过外部exception消息对错误进行分组的方法 )。 如果这会影响您,您可能希望将详细信息放在内部exception中:
throw new KeyNotFoundException( "key was not found", new KeyNotFoundException(serializedKey));
我认为找到问题的最佳方法是在Application.UnhandledException方法中记录给定exception的StackTrace。 通过StackTrace,您可以找到问题的根源(方法的名称,导致exception的文件的名称和行)。 这样,您就可以了解代码的错误。 总是尝试尽可能多地记录。
这是因为windows phone的silverlight不支持wsHttpBinding,所以你将服务改为basicHttpBinding,它会工作