用linq2xml迭代onienumerable

时间:2016-06-10 13:12:13

标签: c# linq-to-xml ienumerable

我很惊讶地看到以下代码中的所有元素都没有被迭代:

IEnumerable<XElement> dataStorageGroupElements = document.Descendants().Where(x => "Xms.Common.DataStorageGroup" == (string)x.Attribute("NodeType"));
int counter = 0;
foreach (XElement dataStorageGroupElement in dataStorageGroupElements)
{
    Console.WriteLine($"Counter={counter++}, NbElements={dataStorageGroupElements.Count()}");
    XElement newParent = GetNewParentForDataStorageGroup(dataStorageGroupElement);
    dataStorageGroupElement.Remove();
    newParent.Add(dataStorageGroupElement);
}

输出是:

Counter=0, NbElements=12
Counter=1, NbElements=12
Counter=2, NbElements=12
Counter=3, NbElements=12
Counter=4, NbElements=12
Counter=5, NbElements=12
Counter=6, NbElements=12

使用ToArray()更改代码以执行枚举可以解决此问题:

IEnumerable<XElement> dataStorageGroupElements = document.Descendants().Where(x => "Xms.Common.DataStorageGroup" == (string)x.Attribute("NodeType")).ToArray();

使用上面的代码,计数器将递增到11。

为什么要跳过某些元素here。但为什么NbElements总是12?它只是第一次评估吗?

1 个答案:

答案 0 :(得分:3)

MSDN中描述了该问题:"Mixed declarative code / imperative code bugs (LINQ to XML)"

  

LINQ to XML包含允许您直接修改XML树的各种方法。您可以添加元素,删除元素,更改元素的内容,添加属性等。修改XML树(LINQ to XML)(C#)中描述了此编程接口。如果您正在迭代其中一个轴(例如Elements),并且在迭代轴时修改XML树,则最终会出现一些奇怪的错误。

     

这个问题有时被称为“万圣节问题”。

基本上,在你懒洋洋地迭代它时修改一些东西是个坏主意。在开始修改内容之前使用ToArray来实现查询的方法是正确的,尽管我个人使用ToList代替ToArray