字典中不存在给定的关键字.哪把钥匙

本文关键字:关键字 钥匙 不存在 字典 | 更新日期: 2023-09-27 18:25:55

有没有一种方法可以以影响所有泛型类的方式获得C#中以下异常中给定键的值?我认为这是微软异常描述中的一个重大遗漏。

字典中不存在给定的关键字。

更好的方法是:

给定的密钥"+钥匙ToString()+"字典中没有。

解决方案可能涉及混合或派生类。

字典中不存在给定的关键字.哪把钥匙

当您试图索引到不存在的东西时,会引发此异常,例如:

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

很多时候,像物体这样的东西会是关键,这无疑会让它更难得到。然而,您总是可以编写以下内容(甚至可以用扩展方法将其封装起来):

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

或更高效(感谢@ScottChamberlain)

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

微软选择不这样做,可能是因为它在大多数对象上使用时都是无用的。自己动手很简单,所以自己动手吧!

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

但是,您可以将调试器设置为在首次引发异常时中断。届时,不存在的键将作为调用堆栈中的值进行访问。

在Visual Studio中,此选项位于以下位置:

调试.rar;例外→公共语言运行时异常&rar;System.Collections.Generic

在那里,您可以选中抛出框。


对于运行时需要信息的更具体的实例,如果您的代码使用IDictionary<TKey, TValue>而不直接绑定到Dictionary<TKey, TValue>,则可以实现自己的字典类,该类提供这种行为。

如果有人在2021年仍然关心,并且能够负担得起迁移到.NET Core,则.NET 5最终告诉我们违规密钥的名称:

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

会给你:

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)

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

至于那些还负担不起搬到Core的人,恐怕没有真正可行的解决方案。用TryGetValue替换所有索引器调用是很麻烦的,更不用说荒谬了。从字典中划分子类实际上是不可能的。是的,您可以声明new索引器,但多态性会消失,因为只有在使用子类的引用时才会调用索引器。最后,创建您自己的Dictionary包装器可能是一个解决方案,但这也是一个不平凡的过程,尤其是如果您想完全复制Dictionary,它不仅实现IDictionary<TKey,TValue>,还实现

System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>
System.Collections.IDictionary
System.Runtime.Serialization.IDeserializationCallback
System.Runtime.Serialization.ISerializable

真是小题大做"只是";以获取异常消息。

如果您想管理密钥未命中,您应该使用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.");
}
string Value = dic.ContainsKey("Name") ? dic["Name"] : "Required Name"

使用此代码,我们将获得"Value"中的字符串数据。如果关键字"Name"存在于字典"dic"中,则获取此值,否则返回"Required Name"字符串。

您可以尝试此代码

Dictionary<string,string> AllFields = new Dictionary<string,string>();  
string value = (AllFields.TryGetValue(key, out index) ? AllFields[key] : null);

如果密钥不存在,它只返回一个null值。

从@BradleyDotNET的anwser借用,这是扩展方法版本:

public static TValue GetValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key) 
{
    if (dictionary.TryGetValue(key, out TValue result)) 
    {
        return result;
    } 
    else 
    {
        throw new KeyNotFoundException($"The given key '{key}' was not present in the dictionary.");
    }
}

在C#7.0或更高版本中,您可以使用out参数修饰符在一行中解决问题,并且只对索引器进行一次调用。它适用于c#7.0或更高版本。

public TItem GetOrException<TKey,TItem>(TKey key) where TKey : IFormattable => 
    dictionary.TryGetValue(key, out var item) ? item : throw new KeyNotFoundException( "Key: " + key.ToString() );

您也可以选择更长的try-catch块,它可以提供更好的异常信息:

public TItem GetOrException<TKey,TItem>(TKey key) where TKey : IFormattable {
    try{ return dictionary[key]; }
    catch (KeyNotFoundException e) { throw new KeyNotFoundException("Key:" + key.ToString(), e);}
}