为什么Dictionary.Add会覆盖我的字典中所有的项?

6

我有一个类型为 Dictionary<string,IEnumerable<string>> 的字典以及一个字符串值的列表。由于某种原因,每次进行添加操作时,字典中的每个值都会被覆盖。我完全不知道为什么会发生这种情况。我确保它不是引用问题,通过在循环中声明和初始化 IEnumberable 对象,使其范围不超出一个迭代范围,并且它仍然发生了这种情况。以下是我的代码:

foreach (string type in typelist)
{
    IEnumerable<string> lst = 
        from row in root.Descendants()
        where row.Attribute("serial").Value.Substring(0, 3).Equals(type)
        select row.Attribute("serial").Value.Substring(3).ToLower();

    serialLists.Add(type, lst);
}

其中typelist是一个IEnumerable<string>root是一个XElement,而serialLists是我的Dictionary


4
你已经“封闭了循环变量”。每次添加 lst 时都会使用最后一个 type 变量。请阅读此内容:http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx 有趣的是,这个问题在C#5中将消失! - dlev
1
我一定会仔细阅读。再次感谢大家的帮助! - Annath
2个回答

10

这是一个捕获迭代器的问题。

尝试:

foreach (string tmp in typelist)
{
   string type = tmp;

或者,我会在添加时评估表达式,即在 .Add 中进行 .ToList():

    serialLists.Add(type, lst.ToList());
第二个选项可能总体上更有效,尽管它会强制评估可能永远不需要的内容。

谢谢!这立刻修复了问题。 - Annath

6
原因是您的 IEnumerable<string> 序列没有被及时填充,而是在需要时才进行填充, foreach 循环完成所有迭代之后。因此,当枚举任何 IEnumerable<string> 序列时,type 变量总会具有 typelist 中最后一个元素的值。
以下是一种简单的解决方法:
foreach (string type in typelist)
{
    string typeCaptured = type;

    IEnumerable<string> lst = 
        from row in root.Descendants()
        where row.Attribute("serial").Value.Substring(0, 3).Equals(typeCaptured)
        select row.Attribute("serial").Value.Substring(3).ToLower();

    serialLists.Add(typeCaptured, lst);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接