抛出KeyNotFoundException时,如何查看未找到哪个键?

时间:2011-08-29 12:19:13

标签: c# .net exception .net-4.0 keynotfoundexception

System.Collections.Generic.Dictionary正在投掷KeyNotFoundException,但我看不出哪个密钥丢失了。我该如何确定?

7 个答案:

答案 0 :(得分:19)

自定义例外:

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
}

答案 1 :(得分:15)

没有办法从异常中辨别出来。您需要为此实现自己的解决方案。

答案 2 :(得分:5)

如果您可以自定义声明字典的实现,则可以通过自定义类型轻松替换System.Collections.Generic.Dictionary,从而抛出更好的KeyNotFoundException。虽然这类似于abatishchev的答案,但我不喜欢他介绍的扩展方法,因为它意味着我们有两种不同的方法来实现完全相同的东西。如果可能,应该避免这种情况。我通过使用“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 :(得分:3)

你不能仅仅通过查看异常。抛出异常时,您必须进入调试器(Visual Studio中的 Debug - &gt; Exceptions ... )并查看已访问的密钥。或者,您可以在代码中捕获异常并将其打印出来(例如,打印到控制台)。

答案 4 :(得分:0)

使用调试器(如果需要,请在Debug-&gt; Exceptions中查看Throw Catch)并查看

答案 5 :(得分:0)

您会认为他们可以将尝试输入的密钥添加到异常中。数据

这就是我所做的

        public static void SetGlobals()
    {
        string currentKey = "None";
        try
        {
            currentKey = "CurrentEnvironment";
            Globals.current_environment = Settings[currentKey];
            currentKey = "apiUrl";
            Globals.api_url = Settings[currentKey];
            currentKey = "whatever";
            Globals.whatever= Settings[currentKey];

            if (AppDomain.CurrentDomain.GetData(".devEnvironment") as bool? == true)
                Globals.api_url = "http://localhost:59164/api";
        }
        catch(KeyNotFoundException)
        {
            DBClass.logEvent("Error", "AppSettings", "Missing Setting: " + currentKey);
        }
    }

答案 6 :(得分:-1)

System.Collections.Generic.KeyNotFoundException已引发

如果您将DotNet Core与Xamarin Studio一起使用,并且出现此错误,则可以检查密钥是否存在,并且具有以下条件:

if (Application.Current.Properties.ContainsKey("userCredentials")) {
    //now process...
}