By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,631 Members | 1,308 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,631 IT Pros & Developers. It's quick & easy.

foreach Iterator - which is more efficient?

P: n/a
Everything I know about looping structures says to be careful about
expressions that need to be evaluated again and again for each
test/increment of a loop.

I came across this piece of code the other day and stopped to think for a
minute about whether it was right or not.
foreach (XmlNode node in doc.SelectNodes("/root/map/");)
{
//Do something
}

Am I missing something here or is this going to perform the Xpath select for
every iteration? Or is it the case that once the iterator has been retrieved
by the foreach statement that it will use the same one for each loop without
evaluating the SelectNodes statement over and over again.

If I was able to read IL - I would look at what was going on here myself.

I've been trained to think about doing this the following way.

XmlNodeList list = doc.SelectNodes("/root/map/");
foreach (XmlNode node in list)
{
//Do something
}

Enlightenment appreciated....
Feb 22 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a
I'm not sure if the compiler is smart enough to optimize this, but number 2
is definitely the way to go in my book.
Peter

--
Co-founder, Eggheadcafe.com developer portal:
http://www.eggheadcafe.com
UnBlog:
http://petesbloggerama.blogspot.com


"Anthony Bouch" wrote:
Everything I know about looping structures says to be careful about
expressions that need to be evaluated again and again for each
test/increment of a loop.

I came across this piece of code the other day and stopped to think for a
minute about whether it was right or not.
foreach (XmlNode node in doc.SelectNodes("/root/map/");)
{
//Do something
}

Am I missing something here or is this going to perform the Xpath select for
every iteration? Or is it the case that once the iterator has been retrieved
by the foreach statement that it will use the same one for each loop without
evaluating the SelectNodes statement over and over again.

If I was able to read IL - I would look at what was going on here myself.

I've been trained to think about doing this the following way.

XmlNodeList list = doc.SelectNodes("/root/map/");
foreach (XmlNode node in list)
{
//Do something
}

Enlightenment appreciated....

Feb 22 '06 #2

P: n/a
Anthony,
Or is it the case that once the iterator has been retrieved
by the foreach statement that it will use the same one for each loop without
evaluating the SelectNodes statement over and over again.
Yes.

If I was able to read IL - I would look at what was going on here myself.


You don't have to be able to read IL. Just check the C# documentation
on how the foreach statement is compiled to a single call to
GetEnumerator (usually from the IEnumerable or IEnumerable<T>
interfaces).
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Feb 22 '06 #3

P: n/a
Compiler generate this:

XmlDocument doc = new XmlDocument();

XmlNodeList list = doc.SelectNodes("/root/map/");

IEnumerator enumerator = list.GetEnumerator();
try
{
XmlNode node;
while (enumerator.MoveNext())
{
node = (XmlNode)enumerator.Current;
// DO SMTH
}
}
finally
{
IDisposable disposable = (IDisposable)enumerator;
if (disposable != null)
disposable.Dispose();
}

Feb 22 '06 #4

P: n/a
Anthony,

The following code produced the *exact* same MSIL for the foreach loop
on my C# 1.1 compiler. As you can see the SelectNodes method is only
executed once.

IEnumerator enumerator = doc.SelectNodes("/root/map/");
try
{
while (enumerator.MoveNext())
{
XmlNode node = (XmlNode)enumerator.Current;
}
}
finally
{
IDisposable disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}

Personally, I prefer the first method you described because it keeps
the scope of local variables as narrow as possible and yet is still
very readable.

Brian

Anthony Bouch wrote:
Everything I know about looping structures says to be careful about
expressions that need to be evaluated again and again for each
test/increment of a loop.

I came across this piece of code the other day and stopped to think for a
minute about whether it was right or not.
foreach (XmlNode node in doc.SelectNodes("/root/map/");)
{
//Do something
}

Am I missing something here or is this going to perform the Xpath select for
every iteration? Or is it the case that once the iterator has been retrieved
by the foreach statement that it will use the same one for each loop without
evaluating the SelectNodes statement over and over again.

If I was able to read IL - I would look at what was going on here myself.

I've been trained to think about doing this the following way.

XmlNodeList list = doc.SelectNodes("/root/map/");
foreach (XmlNode node in list)
{
//Do something
}

Enlightenment appreciated....


Feb 22 '06 #5

P: n/a
Peter Bromberg [C# MVP] <pb*******@yahoo.nospammin.com> wrote:
I'm not sure if the compiler is smart enough to optimize this, but number 2
is definitely the way to go in my book.


Why? It's less readable, leaves an extra variable in scope for no good
reason, and won't perform any better anyway :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Feb 22 '06 #6

P: n/a
Anthony Bouch <an*****@nospamforever.com> wrote:
Everything I know about looping structures says to be careful about
expressions that need to be evaluated again and again for each
test/increment of a loop.

I came across this piece of code the other day and stopped to think for a
minute about whether it was right or not.
foreach (XmlNode node in doc.SelectNodes("/root/map/");)
{
//Do something
}

Am I missing something here or is this going to perform the Xpath select for
every iteration? Or is it the case that once the iterator has been retrieved
by the foreach statement that it will use the same one for each loop without
evaluating the SelectNodes statement over and over again.
Exactly. If it were re-executing SelectNodes each time, you'd keep
getting the first element of the list :)
If I was able to read IL - I would look at what was going on here myself.


Fortunately there's the C# spec to go on as well :)

From the ECMA spec, section 15.8.4:

<quote>
A foreach statement of the form:

foreach (ElementType element in collection) statement

corresponds to one of two possible expansions:

If the collection expression is of a type that implements the
collection pattern (as defined above), the expansion of the foreach
statement is:

<snip - this isn't the normal case>

Otherwise; the collection expression is of a type that implements
System.IEnumerable, and the expansion of the foreach statement is:

IEnumerator enumerator =
((System.IEnumerable)(collection)).GetEnumerator() ;
try {
while (enumerator.MoveNext()) {
ElementType element = (ElementType)enumerator.Current;
statement;
}
}
finally {
IDisposable disposable = enumerator as System.IDisposable;
if (disposable != null) disposable.Dispose();
}

</quote>

Note that the "collection" expression is only evaluated once.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Feb 22 '06 #7

P: n/a
Overwhelmed with the replies - totally clear now and slightly embarrassed
that I didn't check the documentation first.

Thanks

"Anthony Bouch" <an*****@nospamforever.com> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
Everything I know about looping structures says to be careful about
expressions that need to be evaluated again and again for each
test/increment of a loop.

I came across this piece of code the other day and stopped to think for a
minute about whether it was right or not.
foreach (XmlNode node in doc.SelectNodes("/root/map/");)
{
//Do something
}

Am I missing something here or is this going to perform the Xpath select
for every iteration? Or is it the case that once the iterator has been
retrieved by the foreach statement that it will use the same one for each
loop without evaluating the SelectNodes statement over and over again.

If I was able to read IL - I would look at what was going on here myself.

I've been trained to think about doing this the following way.

XmlNodeList list = doc.SelectNodes("/root/map/");
foreach (XmlNode node in list)
{
//Do something
}

Enlightenment appreciated....

Feb 23 '06 #8

P: n/a
Anthony,

I thought it was a good question. And as far as the documentation is
concerned I understand that sometimes you just don't know what keywords
to search on to find what you want. I did a little poking around and
the only place I found that clearly explained how the foreach construct
is compiled was the C# specification (MSDN or ECMA versions).

Brian

Anthony Bouch wrote:
Overwhelmed with the replies - totally clear now and slightly embarrassed
that I didn't check the documentation first.

Thanks


Feb 23 '06 #9

P: n/a
Anthony Bouch <an*****@nospamforever.com> wrote:
Overwhelmed with the replies - totally clear now and slightly embarrassed
that I didn't check the documentation first.


No need for embarrassment. Yes, it's documented - but unless you knew
where to go, it wasn't exactly staring you in the face.

Put it this way - it was a lot less trivial than a lot of questions we
get here :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Feb 23 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.