如果键不存在,C# Dictionary<int, int> 查找会发生啥?

Posted

技术标签:

【中文标题】如果键不存在,C# Dictionary<int, int> 查找会发生啥?【英文标题】:What happens to C# Dictionary<int, int> lookup if the key does not exist?如果键不存在,C# Dictionary<int, int> 查找会发生什么? 【发布时间】:2011-01-09 11:40:16 【问题描述】:

我尝试检查 null 但编译器警告这种情况永远不会发生。我应该寻找什么?

【问题讨论】:

【参考方案1】:

假设您想在键确实存在的情况下获取值,请使用Dictionary&lt;TKey, TValue&gt;.TryGetValue

int value;
if (dictionary.TryGetValue(key, out value))

    // Key was in dictionary; "value" contains corresponding value
 
else 

    // Key wasn't in dictionary; "value" is now 0

(使用ContainsKey,然后索引器使其向上查找键两次,这是毫无意义的。)

请注意,即使您使用引用类型,也无法检查 null - 如果您请求缺少的键,Dictionary&lt;,&gt; 的索引器将抛出异常,而不是返回 null。 (这是Dictionary&lt;,&gt;Hashtable 之间的一个很大区别。)

【讨论】:

@JonSkeet TryGetValue 不是也在做双重查找吗(as stated in this question body)? @nawfal:我没有看到任何迹象表明该问题表明了这一点。它说它比ContainsKey 做了更多的工作,这是真的,因为它也必须提取价值。但它并没有进行两次查找。 天真地,我一直期待 null,但对于 Dictionary,这将返回枚举中的“0”等价物。【参考方案2】:

如果字典不包含您的密钥,字典会引发 KeyNotFound 异常。

正如建议的那样,ContainsKey 是适当的预防措施。 TryGetValue也有效。

这允许字典更有效地存储 null 值。如果没有这种行为,检查 [] 运算符的空结果将指示空值或输入键不存在,这是不好的。

【讨论】:

更多信息可以在 MSDN 中找到:msdn.microsoft.com/en-gb/library/9tee9ht2.aspx【参考方案3】:

如果您只是在尝试添加新值之前进行检查,请使用ContainsKey 方法:

if (!openWith.ContainsKey("ht"))

    openWith.Add("ht", "hypertrm.exe");

如果您要检查该值是否存在,请使用 Jon Skeet 的回答中所述的 TryGetValue 方法。

【讨论】:

因为如果您在包含后立即获取,您将通过哈希表解析密钥查找两次。 Wintellect PowerCollections 还具有GetValueElseAdd 方法,如果您要在不存在的情况下添加,则您可以给这些方法一个值(或Func&lt;TValue&gt;)来保存插入上的分辨率。我想没有进入.NET库的原因是因为如果您在缓存样式中使用它,则添加路径的频率较低] @rub:我想这取决于代码的用途。如果您想使用该值,我同意TryGetValue 会更好,但是如果您想检查字典是否包含键以避免重复添加,我会说ContainsKey 一样好(如果不是更好)。 @Fredrik:如果您想要进行遏制检查,那么是的,值得使用 ContainsKey。请注意,此答案的示例代码中并非如此。 @Jon: 是的,我实际上错过了添加后立即获取的附加值。 @Mork:你说得对,我同意。我评论的原因是该帖子没有明确说明您通常想要执行 ContainsKey(仅)或 TryGet(包含 + Get)或 TryGet / Add(在帖子中的代码示例中没有另一个 Get)【参考方案4】:

在尝试提取值之前,您应该检查 Dictionary.ContainsKey(int key)。

Dictionary<int, int> myDictionary = new Dictionary<int, int>();
myDictionary.Add(2,4);
myDictionary.Add(3,5);

int keyToFind = 7;
if(myDictionary.ContainsKey(keyToFind))

    myValueLookup = myDictionay[keyToFind];
    // do work...

else

    // the key doesn't exist.

【讨论】:

为什么要让它进行两次查找? @mookid:在我看来不是。我们的想法是尝试查找密钥,如果找到则采取一种行动,否则采取另一种行动,对吗? @Jon - 老实说?因为我不知道TryGetValue。谢天谢地,我现在这样做了,所以我以后会知道的。我将保持这个答案不变,尽管 'cos 讨论很有价值。 @JonSkeet 因为在 C# 7 之前,您不能在 lambda 表达式中使用 TryGetValue。虽然这确实让我认为 C# 的新扩展将是类似于 null 合并运算符的 catch 运算符。 @NetMage:你可以在 lambda 表达式中做到这一点 - 只是不是一个表达式主体的 lambda 表达式。【参考方案5】:

辅助类很方便:

public static class DictionaryHelper

    public static TVal Get<TKey, TVal>(this Dictionary<TKey, TVal> dictionary, TKey key, TVal defaultVal = default(TVal))
    
        TVal val;
        if( dictionary.TryGetValue(key, out val) )
        
            return val;
        
        return defaultVal;
    

【讨论】:

有时我想知道为什么没有将它添加到标准库中。如果没有条目,几乎所有使用 hashmap 的语言都会返回 null,而不是异常。字典中不存在的项目不是异常行为。 @AdamHess - 这就是为什么你在 c# 中有 Hashtable() ......不幸的是,你的钥匙被装箱了...... :(【参考方案6】:

ContainsKey 是你要找的。​​p>

【讨论】:

【参考方案7】:

您可能应该使用:

if(myDictionary.ContainsKey(someInt))

  // do something

不能检查null的原因是这里的key是值类型。

【讨论】:

值的类型有点无关紧要,因为检查 null 不会有预期的效果。 @Johannes,Jon 的解决方案当然要好很多,但是提问者确实说他检查了 key 是否存在,并且是 Dictionary,所以 key 也是 value在这里输入。【参考方案8】:

考虑封装这个特定字典的选项,并提供一种方法来返回该键的值:

public static class NumbersAdapter

    private static readonly Dictionary<string, string> Mapping = new Dictionary<string, string>
    
        ["1"] = "One",
        ["2"] = "Two",
        ["3"] = "Three"
    ;

    public static string GetValue(string key)
    
        return Mapping.ContainsKey(key) ? Mapping[key] : key;
    

然后你可以管理这个字典的行为。

例如这里:如果字典没有键,则返回您通过参数传递的键。

【讨论】:

【参考方案9】:
int result= YourDictionaryName.TryGetValue(key, out int value) ? YourDictionaryName[key] : 0;

如果键存在于字典中,则返回键的值,否则返回 0。

希望这段代码能帮到你。

【讨论】:

如果key存在,这段代码会查找两次。 TryGetValue 就够了,用value 代替result

以上是关于如果键不存在,C# Dictionary<int, int> 查找会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

C# Dictionary 用法;

Python 字典(Dictionary)

C# Dictionary<> 和可变键

C#中Dictionary的TryGetValue和Contains

C#中Dictionary的TryGetValue和Contains

C#基础 Dictionary存储自定义对象作为键值