Подтвердить что ты не робот

Когда вызывается KeyNotFoundException, как я могу узнать, какой ключ не найден?

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

4b9b3361

Ответ 1

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

Ответ 2

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

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
}

Ответ 3

Если вы можете настроить реализацию, в которой объявлен словарь, вы можете легко заменить 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);
            }
        }
    }
}

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

Ответ 4

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

Ответ 5

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