Когда выдается KeyNotFoundException, как узнать, какой ключ не найден? - PullRequest
29 голосов
/ 29 августа 2011

A System.Collections.Generic.Dictionary выбрасывает KeyNotFoundException, но я не вижу, какой ключ предположительно отсутствует. Как мне это определить?

Ответы [ 5 ]

19 голосов
/ 29 августа 2011

Пользовательское исключение:

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

Удобный метод расширения:

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

Использование:

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
}
15 голосов
/ 29 августа 2011

Нет никакого способа отличить это от исключения.Для этого вам нужно реализовать собственное решение.

5 голосов
/ 04 марта 2013

Если вы можете настроить реализацию, в которой объявлен словарь, вы можете легко заменить System.Collections.Generic.Dictionary на пользовательский тип, выдав более приятное KeyNotFoundException.Хотя это похоже на ответ Абатищева, мне не нравится метод расширения, который он ввел, поскольку это означает, что у нас есть два разных способа достичь абсолютно одинаковой цели.Этого следует избегать, если это возможно.Я решил проблему, используя вместо этого «NiceDictionary», который можно использовать точно так же, как исходный Dictinary, используемый в качестве базового класса.Реализация почти тривиальна:

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

Как уже говорилось, вы можете использовать его точно так же, как и оригинальный словарь.Он волшебным образом работает из-за переопределенного оператора массива ([]).

3 голосов
/ 29 августа 2011

Вы не можете просто смотреть на исключение. Вам придется взломать отладчик при возникновении исключения ( Debug -> Exceptions ... в Visual Studio) и посмотреть, к какому ключу был получен доступ. В качестве альтернативы вы можете перехватить исключение в коде и распечатать его (например, на консоли).

0 голосов
/ 29 августа 2011

используйте отладчик (при необходимости проверьте ThrowOnCatch в Debug-> Exceptions) и посмотрите

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...