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

发布于 2024-12-02 01:45:12 字数 117 浏览 1 评论 0原文

System.Collections.Generic.Dictionary 抛出 KeyNotFoundException,但我看不到哪个键应该丢失。我如何确定这一点?

A System.Collections.Generic.Dictionary is throwing KeyNotFoundException, but I can't see which key is supposedly missing. How do I determine this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

注定孤独终老 2024-12-09 01:45:12

自定义异常:

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
}

Custom exception:

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

Handy extension method:

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

Usage:

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
}
铃予 2024-12-09 01:45:12

没有办法从异常中看出这一点。您需要为此实施自己的解决方案。

There is no way to tell this from the exception. You need to implement your own solution for this.

野稚 2024-12-09 01:45:12

如果您可以自定义声明字典的实现,则可以轻松地用自定义类型替换 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);
            }
        }
    }
}

如上所述,您可以像使用原始字典一样精确地使用它。由于覆盖了数组运算符([]),它神奇地工作了。

If it is possible for you to customize the implementation where the dictionary is declared, you can easily replace System.Collections.Generic.Dictionary by a custom type throwing a nicer KeyNotFoundException. While this is similar to the answer of abatishchev, I don't like the extension method he introduced, since it means that we have two different ways to achieve the exactly same thing. This should be avoided if possible. I solved the problem by using a "NiceDictionary" instead, which can be used exactly like the original Dictinary used as base class. The implementation is almost 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);
            }
        }
    }
}

As said, you can use it exaclty as you would use the original Dictionary. It magically works because of the overridden array operator ([]).

梦回旧景 2024-12-09 01:45:12

你不能仅仅通过查看异常来判断。当抛出异常时,您必须中断调试器(Visual Studio 中的“调试 -> 异常...”)并查看访问了哪个键。或者,您可以捕获代码中的异常并将其打印出来(例如打印到控制台)。

You can't just by looking at the exception. You will have to break into the debugger when the exception is thrown (Debug -> Exceptions... in Visual Studio) and see what key has been accessed. Alternatively you could catch the exception in code and print it out (e.g. to the console).

So要识趣 2024-12-09 01:45:12

使用调试器(如果需要,检查 Debug->Exceptions 中的 ThrowOnCatch)并查看

use the debuger (if needed check the ThrowOnCatch in Debug->Exceptions) and have a look

娇纵 2024-12-09 01:45:12

我使用了这个扩展方法

internal static class KeyNotFoundExceptionExtensions
{
    public static string GetKeyValue(this KeyNotFoundException ex)
    {
        var match = Regex.Match(ex.Message, @"'(.*?)'");
        if (match.Success)
            return match.Groups[1].Value;

        throw ex;
    }
}

I used this extension method

internal static class KeyNotFoundExceptionExtensions
{
    public static string GetKeyValue(this KeyNotFoundException ex)
    {
        var match = Regex.Match(ex.Message, @"'(.*?)'");
        if (match.Success)
            return match.Groups[1].Value;

        throw ex;
    }
}
盗琴音 2024-12-09 01:45:12

你会认为他们可以将尝试的密钥添加到异常中。

这就是我所做的

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

you would think that they could add the attempted key to the exception.data

this is what i did

        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);
        }
    }
是伱的 2024-12-09 01:45:12

System.Collections.Generic.KeyNotFoundException 已抛出

如果您将 DotNet Core 与 Xamarin Studio 一起使用并且收到此错误,您可以检查密钥是否存在并满足以下条件:

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

System.Collections.Generic.KeyNotFoundException has been thrown

If you are using DotNet Core with Xamarin Studio and you get this error you can check if the key exists with the following condition:

if (Application.Current.Properties.ContainsKey("userCredentials")) {
    //now process...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文