我有一个涉及字典的神秘情况,我从字典中枚举键,但字典不包含它所说的某些键。
Dictionary<uint, float> dict = GetDictionary(); // Gets values, 6268 pairs
foreach(uint key in dict.Keys)
{
if (!dict.ContainsKey(key))
Console.WriteLine("Wat? "+key);
}
以上将打印 6268 个密钥中的两个。这两个键没有什么特别之处,都是小于 Int32.MaxValue 的正值(369099203 和 520093968)。
对计数的检查揭示了这一点:
Console.WriteLine(dict.Count); // 6268
Console.WriteLine(dict.Keys.Count()); // 6268
Console.WriteLine(dict.Keys.Count(dict.Keys.Contains)); // 6266
这是在 .NET4.5 CLR 下运行的单线程.NET4 代码。字典是香草,Dictionary<uint, float>
即没有自定义相等比较器。我假设由于 uint/int 差异而发生哈希问题,但不ContainsKey(key)
应该保证字典的 Key 集合中返回的所有键都是真的吗?尤其是当您只查看下面代码片段中的 KeyCollection 对象时,总计数和包含对象的计数是关闭的,这感觉像是一种奇怪的ICollection
行为。
编辑:
正如预期的那样,似乎有一个合理的解释:集合在初始化期间被两个并发线程修改过。当某些东西“有时会中断”时,这是一个线程问题,果然如此。从多个线程访问一个 dict 显然会扰乱内部状态,使其在其生命周期的剩余时间内处于半功能状态,但不会导致任何异常。
我要切换到并发字典,并可能删除这个问题。谢谢。