foreach and XPathNodeIterator - finally together

| 8 Comments | 3 TrackBacks

This one little improvement in System.Xml 2.0 Beta2 is sooo cool anyway: XPathNodeIterator class at last implements IEnumerable! Such unification with .NET iteration model means we can finally iterate over nodes in an XPath selection using standard foreach statement:

XmlDocument doc = new XmlDocument();
doc.Load("orders.xml");
XPathNavigator nav = doc.CreateNavigator();
foreach (XPathNavigator node in nav.Select("/orders/order"))
    Console.WriteLine(node.Value);
Compare this to what we have to write in .NET 1.X:
XmlDocument doc = new XmlDocument();
doc.Load("../../source.xml");
XPathNavigator nav = doc.CreateNavigator();
XPathNodeIterator ni = nav.Select("/orders/order");
while (ni.MoveNext())      
  Console.WriteLine(ni.Current.Value);
Needless to say - that's the case when just a dozen lines of code can radically simplify a class's usage and improve overall developer's productivity. How come this wasn't done in .NET 1.1 I have no idea.

And how come the MSDN documentation for the class still doesn't mention this cool feature - I have no idea either.

Related Blog Posts

3 TrackBacks

TrackBack URL: http://www.tkachenko.com/cgi-bin/mt-tb.cgi/437

8 Comments

ohhhhh no i cant believe how good are u u saved my butt

:)

Yes, Dare's post just popped up in my RSS Bandit.

Nice to have an explanation for the at-first-glance-excessive cloning that is going on.

I personally intend to use foreach (or rather, For Each - VB.NET shop here :p) on XPathNavigator - I favor readability.

But be prepared for the hordes of integrists that will call you a resource waster for using it...

Thanks for the discussion.

Oh, I see.
Have you seen Andrew Kimball's comment at Dare's post ?

Yes, cloning XPathNavigator is cheap, but I talked about an *XPathNodeIterator* being cloned twice. And looking at the Beta 2 code with Reflector, I see that cloning an XPathSelectionIterator for example involves cloning the XPath query's tree recursively.

Not a big deal really in the vast majority of cases, but still something I bet Rico Mariani would frown upon... It's like the overloads of String.Compare() that take offset+length versus using String.Substring(), or String.Split()... when you're writing code that will be executed a lot of times it can become significant in terms of GC pressure.

Well, cloning XPathNavigator is cheap by design and is happening all the time. And one object allocation - I can live with it :)

I wondered about the same - after writing the above code for the twelfth time in .NET 1.1 I was pretty much angry after XPathNodeIterator.

The only argument I can see against IEnumerable is that there is at least one additional allocation (the enumerator) when using it.

And in fact if you look at how IEnumerable is implemented by XPathNodeIterator, it leads to System.Xml.XPath.XPathNodeIterator+Enumerator.ctor(XPathNodeIterator) which Clone()s the XPathNodeIterator twice ! So your foreach on a XPathNodeIterator may be more convenient but it is certainly more heavyweight than straight MoveNext().

Again the old tradeoff between convenience and performance... I'm sure this was the cause of some debate in Redmond !

about fecking time

Leave a comment