给定的密​​钥不在字典中.哪个关键?

And*_*eas 69 c# generics dictionary exception

有没有办法以一种影响所有泛型类的方式在C#中的以下异常中获取给定键的值?我认为这是微软的异常描述中的一个重大缺失.

"The given key was not present in the dictionary."
Run Code Online (Sandbox Code Playgroud)

更好的方法是:

"The given key '" + key.ToString() + "' was not present in the dictionary."
Run Code Online (Sandbox Code Playgroud)

解决方案可能涉及mixins或派生类.

Bra*_*NET 61

当您尝试索引不存在的内容时抛出此异常,例如:

Dictionary<String, String> test = new Dictionary<String,String>();
test.Add("Key1,"Value1");
string error = test["Key2"];
Run Code Online (Sandbox Code Playgroud)

很多时候,像物体这样的东西将成为关键,这无疑会让它变得更难.但是,您始终可以编写以下内容(或者甚至将其包装在扩展方法中):

if (test.ContainsKey(myKey))
   return test[myKey];
else
   throw new Exception(String.Format("Key {0} was not found", myKey));
Run Code Online (Sandbox Code Playgroud)

或更高效(感谢@ScottChamberlain)

T retValue;
if (test.TryGetValue(myKey, out retValue))
    return retValue;
else
   throw new Exception(String.Format("Key {0} was not found", myKey));
Run Code Online (Sandbox Code Playgroud)

微软选择不这样做,可能是因为它在大多数对象上使用时都没用.它很简单,可以自己做,所以只需滚动自己!

  • 执行`ContainsKey`然后索引器将在字典中导致两次查找.执行`TryGetValue`只能进行一次查找,你可以使用它的布尔输出来选择你的if/else块. (13认同)

Sam*_*ell 16

在一般情况下,答案是否定的.

但是,您可以将调试器设置为在首次抛出异常时中断.此时,不存在的密钥将作为调用堆栈中的值访问.

在Visual Studio中,此选项位于:

Debug→Exceptions ...→公共语言运行时异常→System.Collections.Generic

在那里,你可以检查Thrown框.


对于在运行时需要信息的更具体的实例,只要您的代码使用IDictionary<TKey, TValue>而不是直接绑定Dictionary<TKey, TValue>,您就可以实现自己的字典类来提供此行为.

  • VS 2017 (v15.5.7) 将其设置为:调试 -&gt; Windows -&gt; 异常设置 -&gt; 然后检查 System.Collections.Generic.KeyNotFoundException (2认同)

Ste*_*dis 13

如果有人在 2021 年仍然关心并有能力迁移到 .NET Core,.Net 5 终于告诉我们有问题的密钥的名称:

class Program
{
    static void Main(string[] args)
    {
        Dictionary<string, object> dictionary = new()
        {
            ["foo"] = new object()
        };
        Console.WriteLine(dictionary["bar"]);
    }
}
Run Code Online (Sandbox Code Playgroud)

会给你:

Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key 'bar' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at KnfTest.Program.Main(String[] args)
Run Code Online (Sandbox Code Playgroud)

.Net Framework 4.8 中的相同代码给出了旧的可怕消息。

至于那些无力迁移到 Core 的人,恐怕还没有真正可行的解决方案。用 替换所有索引器调用TryGetValue是很麻烦的 - 更不用说是荒谬的。从 Dictionary 派生子类实际上是不可能的。是的,您可以声明一个new索引器,但是多态性就会消失,因为只有在使用子类的引用时才会调用您的索引器。最后,创建自己的字典包装器可能是一个解决方案,但这又是一个不平凡的过程,特别是如果您想精确复制字典,它不仅实现而且IDictionary<TKey,TValue>还实现:

System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>
System.Collections.IDictionary
System.Runtime.Serialization.IDeserializationCallback
System.Runtime.Serialization.ISerializable
Run Code Online (Sandbox Code Playgroud)

对于异常消息来说,“仅仅”就有点过分了。

  • 我不敢相信微软花了这么多年才承认从第一天起就应该这样做。它总共可以为世界各地的开发人员节省数十万个小时。 (3认同)

gab*_*bba 8

如果您想管理关键未命中,您应该使用TryGetValue

https://msdn.microsoft.com/en-gb/library/bb347013(v=vs.110).aspx

string value = "";
if (openWith.TryGetValue("tif", out value))
{
    Console.WriteLine("For key = \"tif\", value = {0}.", value);
}
else
{
    Console.WriteLine("Key = \"tif\" is not found.");
}
Run Code Online (Sandbox Code Playgroud)