简体   繁体   English

用linq2xml遍历ienumerable

[英]iterating over ienumerable with linq2xml

I was surprised to see that not all of my elements in the following code are being iterated: 我很惊讶地发现以下代码中的所有元素都没有被迭代:

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);
}

Output is: 输出为:

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

Changing the code to execute enumeration with ToArray() fixes this issue: 更改代码以使用ToArray()执行枚举可解决此问题:

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

With the above code the counter is being increment to 11. 使用上面的代码,计数器将递增到11。

Why some elements are being skipped is described here . 为什么这里会跳过某些元素。 But why is NbElements always 12? 但是为什么NbElements总是12? Is it only evaluated the first time? 只是第一次评估吗?

The problem is described in MSDN: "Mixed declarative code / imperative code bugs (LINQ to XML)" : 在MSDN中描述了该问题: “混合的声明性代码/命令性代码错误(LINQ to XML)”

LINQ to XML contains various methods that allow you to modify an XML tree directly. LINQ to XML包含各种方法,使您可以直接修改XML树。 You can add elements, delete elements, change the contents of an element, add attributes, and so on. 您可以添加元素,删除元素,更改元素的内容,添加属性,等等。 This programming interface is described in Modifying XML Trees (LINQ to XML) (C#). 修改XML树(从LINQ到XML)(C#)中描述了此编程接口。 If you are iterating through one of the axes, such as Elements, and you are modifying the XML tree as you iterate through the axis, you can end up with some strange bugs. 如果要遍历一个轴(例如Elements),并且要在遍历轴的同时修改XML树,则可能会遇到一些奇怪的错误。

This problem is sometimes known as "The Halloween Problem". 该问题有时被称为“万圣节问题”。

Basically, modifying something while you're lazily iterating over it is a bad idea. 基本上,在您懒惰地对其进行迭代时进行修改是一个坏主意。 Your approach of using ToArray to materialize the query before you start modifying things is the right one, although I'd personally use ToList instead of ToArray . 尽管我个人会使用ToList而不是ToArray ,但是在开始修改事物之前,使用ToArray来实现查询的方法是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM