Когда словарь бросает 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));
Вы должны записать трассировку стека, чтобы вы могли видеть, откуда исходит ошибка. –