如果键不存在,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<TKey, TValue>.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<,>
的索引器将抛出异常,而不是返回 null。 (这是Dictionary<,>
和Hashtable
之间的一个很大区别。)
【讨论】:
@JonSkeet TryGetValue 不是也在做双重查找吗(as stated in this question body)? @nawfal:我没有看到任何迹象表明该问题表明了这一点。它说它比ContainsKey
做了更多的工作,这是真的,因为它也必须提取价值。但它并没有进行两次查找。
天真地,我一直期待 null,但对于 Dictionary如果字典不包含您的密钥,字典会引发 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<TValue>
)来保存插入上的分辨率。我想没有进入.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考虑封装这个特定字典的选项,并提供一种方法来返回该键的值:
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的TryGetValue和Contains