c# .net exception .net-4.0 keynotfoundexception

c# - Cuando se lanza KeyNotFoundException, ¿cómo puedo ver qué clave no se encontró?



.net .net-4.0 (5)

Un System.Collections.Generic.Dictionary está lanzando KeyNotFoundException , pero no puedo ver cuál es la clave que supuestamente falta. ¿Cómo puedo determinar esto?


Excepción personalizada:

class WellknownKeyNotFoundException : KeyNotFoundException { public WellknownKeyNotFoundException(object key, string message) : this(key, message, null) { } public WellknownKeyNotFoundException(object key, string message, Exception innerException) : base(message, innerException) { this.Key = key; } public object Key { get; private set; } }

Método de extensión práctica:

public TValue GetValue<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) { try { return dic[key]; } catch (KeyNotFoundException ex) { throw new WellknownKeyNotFoundException((object)key, ex.InnerException); } }

Uso:

var foo = new Foo(); var bar = new Bar(); IDictionary<Foo, Bar> dic = new Dictinary<Foo, Bar> { { foo, bar } }; try { dic.GetValue(foo); } catch (WellknownKeyNotFoundException ex) { var key = (Foo)ex.Key; Assert.AreEqual(foo, key); // should be }


No hay manera de decir esto de la excepción. Necesitas implementar tu propia solución para esto.


No puedes solo mirando la excepción. Tendrá que irrumpir en el depurador cuando se lance la excepción ( Depuración -> Excepciones ... en Visual Studio) y ver a qué clave se ha accedido. Alternativamente, puede capturar la excepción en el código e imprimirla (por ejemplo, en la consola).


Si es posible personalizar la implementación donde se declara el diccionario, puede reemplazar fácilmente System.Collections.Generic.Dictionary por un tipo personalizado lanzando una mejor KeyNotFoundException. Si bien esto es similar a la respuesta de abatishchev, no me gusta el método de extensión que introdujo, ya que significa que tenemos dos formas diferentes de lograr exactamente lo mismo. Esto debe evitarse si es posible. Resolví el problema usando un "NiceDictionary" en su lugar, que se puede usar exactamente igual que el original Dictinary utilizado como clase base. La implementación es casi trivial:

/// <summary> /// This is a nice variant of the KeyNotFoundException. The original version /// is very mean, because it refuses to tell us which key was responsible /// for raising the exception. /// </summary> public class NiceKeyNotFoundException<TKey> : KeyNotFoundException { public TKey Key { get; private set; } public NiceKeyNotFoundException(TKey key, string message) : base(message, null) { this.Key = key; } public NiceKeyNotFoundException(TKey key, string message, Exception innerException) : base(message, innerException) { this.Key = key; } } /// <summary> /// This is a very nice dictionary, because it throws a NiceKeyNotFoundException that /// tells us the key that was not found. Thank you, nice dictionary! /// </summary> public class NiceDictionary<TKey, TVal> : Dictionary<TKey, TVal> { public new TVal this[TKey key] { get { try { return base[key]; } catch (KeyNotFoundException knfe) { throw new NiceKeyNotFoundException<TKey>(key, knfe.Message, knfe.InnerException); } } set { try { base[key] = value; } catch (KeyNotFoundException knfe) { throw new NiceKeyNotFoundException<TKey>(key, knfe.Message, knfe.InnerException); } } } }

Como se dijo, puede usarlo exactamente como usaría el Diccionario original. Funciona mágicamente debido al operador de matriz anulado ([]).


use el depurador (si es necesario, verifique ThrowOnCatch en Debug-> Exceptions) y eche un vistazo