What is the “best practice” way of manually iterating (i.e., one at a time with a “next” button) over a set of XElements in my XDocument? Say I select the set of elements I want thusly:
var elems = from XElement el in m_xDoc.Descendants()
where (el.Name.LocalName.ToString() == "q_a")
select el;
I can use an IEnumerator to iterate over them, i.e.,
IEnumerator m_iter;
But when I get to the end and I want to wrap around to the beginning if I call Reset() on it, it throws a NotSupportedException. That’s because, as the Microsoft C# 2.0 Specification under chapter 22 “Iterators” says “Note that enumerator objects do not support the IEnumerator.Reset method. Invoking this method causes a System.NotSupportedException to be thrown .”
So what IS the right way of doing this? And what if I also want to have bidirectional iteration, i.e., a “back” button, too?
Someone on a Microsoft discussion forum said I shouldn’t be using IEnumerable directly anyway. He said there was a way to do what I want with LINQ but I didn’t understand what. Someone else suggested dumping the XElements into a List with ToList(), which I think would work, but I wasn’t sure it was “best practice”. Thanks in advance for any suggestions!
The solution is very simple. Just create a List out of your XElements collection.
You can enumerate through it via the indexer
elems[i]and jump back and forth. Just store the current index in a variable, and decrement/increment it on a button click (with wrap-around).The xml you have is parsed on demand by your linq query (see MSDN for deferred execution and lazy evaluation in Linq to XML). Even if it would support
IEnumerable.Reset(), it would have to parse it again every time. If you call.ToList<T>()it parses all descendant elements once and loads them into the memory.