手动迭代选定的XML元素(C#,XDocument)

手动迭代选定的XML元素(C#,XDocument),c#,.net,xml,iterator,linq-to-xml,C#,.net,Xml,Iterator,Linq To Xml,对XDocument中的一组元素进行手动迭代的“最佳实践”方法是什么(即,一次迭代一个,并按“下一步”按钮)?假设我选择了我想要的元素集: var elems = from XElement el in m_xDoc.Descendants() where (el.Name.LocalName.ToString() == "q_a") select el; 我可以使用IEnumerator对它们进行迭代,即。, IEnumerator m_it

对XDocument中的一组元素进行手动迭代的“最佳实践”方法是什么(即,一次迭代一个,并按“下一步”按钮)?假设我选择了我想要的元素集:

var elems = from XElement el in m_xDoc.Descendants()
            where (el.Name.LocalName.ToString() == "q_a") 
            select el;
我可以使用IEnumerator对它们进行迭代,即。, IEnumerator m_iter

但是当我到了结尾,如果我调用Reset(),我想回到开头,它会抛出一个NotSupportedException。这是因为,正如第22章“迭代器”中的Microsoft C#2.0规范所说,“请注意,枚举器对象不支持IEnumerator.Reset方法。调用此方法会引发System.NotSupportedException。”

那么,正确的做法是什么呢?如果我还想进行双向迭代,也就是“后退”按钮,该怎么办


微软论坛上有人说我无论如何都不应该直接使用IEnumerable。他说有一种方法可以让林克做我想做的事,但我不明白是什么。其他人建议使用ToList()将Xelement转储到列表中,我认为这会起作用,但我不确定这是“最佳实践”。提前感谢您的建议

解决方案非常简单。只需从XElements集合中创建一个列表

var elems = (from XElement el in m_xDoc.Descendants()
            where (el.Name.LocalName.ToString() == "q_a") 
            select el).ToList();
您可以通过索引器
elems[i]
进行枚举,并来回跳转。只需将当前索引存储在一个变量中,然后单击按钮(使用环绕)即可减少/增加它

linq查询会根据需要解析您拥有的xml(有关详细信息,请参阅MSDN)。即使它支持
IEnumerable.Reset()
,每次都必须再次解析它。如果调用
.ToList()
它会一次性解析所有子元素并将它们加载到内存中。

很少需要直接使用枚举器;只需在
elems
上使用
foreach
。这里重复两次:

// first time
foreach(var item in elems) {...}
// second time
foreach(var item in elems) {...}

无需使用
Reset()
-它只需为您使用
GetEnumerator()
两次,这是正确的方法。如果出于任何原因无法运行查询两次,或者希望随机访问而不是顺序访问,那么您必须将其缓冲-可能会将其放入带有
ToList()

的列表中,我认为
foreach
循环不是op要搜索的。他只想在用户按下按钮时获取下一个元素。我认为他最好把数据存储到一个列表中。