2011-07-03 2 views
5

У меня есть приложение C# Silverlight, которое случайно выбрасывает «KeyNotFoundException». Я понятия не имею, какой ключ нельзя найти. Это привело меня к двум вопросам:KeyNotFoundException info

  1. Имеет ли KeyNotFoundException магазин/раскрывает, какой ключ он пытался найти? Когда я посмотрел в documentation, я не увидел ничего, что подразумевало, что эта информация доступна.
  2. Я ломаю/регистрирую это исключение в общем обработчике событий Application.UnhandledException. Мой вопрос: если я поймаю событие здесь, могу ли я преобразовать ExceptionObject в исключение KeyNotFoundException и все еще получить ключевую информацию, если ее выставят, как было задано в # 1?

Большое вам спасибо за помощь!

+1

Вы должны записать трассировку стека, чтобы вы могли видеть, откуда исходит ошибка. –

ответ

4

A 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 собственности они KeyNotFoundException, чтобы точно определить, где проблема происходит. Все исключения имеют свойство StackTrace, поэтому вам не нужно заботиться о том, какой тип исключения был в вашем глобальном обработчике ошибок. Например:

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 
     } 
    } 
3

Я думаю, что лучший способ найти проблему - зарегистрировать StackTrace данного исключения в методе Application.UnhandledException. По StackTrace вы можете найти происхождение проблемы (имя метода, имя и строку файла, вызывающего исключение). Таким образом, вы можете понять, что не так с вашим кодом. Всегда старайтесь записывать столько, сколько сможете.

4

Когда словарь бросает 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));

+0

Большинство ответов revelant. – Aeron

0

Это происходит потому, что для окон Silverlight телефона не поддерживает WsHttpBinding, так что вы измените вам обслуживание в BasicHttpBinding и он будет работать

Смежные вопросы