Welcome to MSDN Blogs Sign in | Join | Help

Enumerating over arrays with for vs. foreach

Brad Abrams forwarded an interesting question to me this morning

 

Questions:

What is the difference between enumerating an array using for versus foreach ?

What is the recommended practice and why?

 

I did a quick analysis for him which he has just posted in full.  Have a look see.
Published Thursday, April 29, 2004 10:45 AM by ricom

Comments

# re: Enumerating over arrays with for vs. foreach

Rico, and what do you say about Joshua Allen's similar analysis on using loops?

"Loopy Decisions"
(http://www.netcrucible.com/blog/PermaLink.aspx?guid=1becbd8e-5b9f-40f0-bddf-994aeb580028)

thanks,
Slavo.
Thursday, April 29, 2004 7:42 PM by Slavo Furman

# re: Enumerating over arrays with for vs. foreach

Well basically he's saying the exact same thing as me. There's no difference between the first two cases and in any case there isn't ever likely to be enough difference that you should change your coding style.

But the most important thing he says is that, whatever you do, if you're going to make a change like this, do measure it in your own scenarios to see what you'd be getting. Who knows, maybe in a more complex function the optimizer will have a heart-attack and not be able to reduce the code down properly.

For my part, I just would like to remind you that this is all about arrays and not ArrayLists or other collection classes.

Quoteing from my other message:

See the "Enumeration Overhead" section in http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/scalenetchapt05.asp -- searching for "foreach" in that same document will give other illustrations and guidance.
Thursday, April 29, 2004 7:52 PM by Rico Mariani

# re: Enumerating over arrays with for vs. foreach

Hi Rico,
A question related to this has been occuring to me also. Whilst the above makes much sense, enumerating an array occurs far less frequently than enumerating a [custom] collection. When I say custom collection, I mean a total, type-safe collection (rather than one being a simple wrapper around ArrayList or something).

Ie. The data members of such a collection may look similar to:

private const int DefaultCapacity = 16;
private int count = 0;
private Item[] itemList;

Where itemList expands to reach contain items as they are added. This means that count will never exceed itemList.Length. However, I would guess that the JIT wont be clever enough to reach this conclusion and thus add the bounds checking. Even when an index is made on the collection:

public Item this[ int index ]
{
get
{
if ( index < 0 || index >= count )
throw new IndexOutOfRange...

return itemList[ index ];
}
}

I already put a bounds check here obviously, but because I'm using 'count' instead of 'itemList.Length' would there be another one added by the JIT? Of course I could look at the debug output, and I will if it becomes a problem for me (at the moment, I'm just interested to see if it may be an issue :)

Also, if the above does pose a problem for the JIT, is this still applicable when using generic collection in Whidbey. Or is the JIT more intellegent with them (I don't have access to Whidbey atm)?

I'm more interested in the foreach case in custom collections, as I generally use foreach in this case rather than iterating over them using for.

Thanks,
n!
Tuesday, May 04, 2004 1:51 AM by nfactorial

# re: Enumerating over arrays with for vs. foreach

The jit wouldn't have any way of knowing that your "count" is strictly less than the array length in all cases so yes I'd expect you to incur a second test until maybe some day when we could do some very deep analysis and still jit fast enough.

You could remove the index < 0 test if you're willing to throw the array bounds check exception instead.

Depending on your use of the collection it may or may not make a difference. I'd expect most times it wouldn't end up mattering much. Usage is everything.
Tuesday, May 04, 2004 7:12 AM by Rico Mariani

# re: Enumerating over arrays with for vs. foreach

By the way, what you have looks remarkably like System.ArrayList I was wondering why you didn't just use that?
Tuesday, May 04, 2004 7:14 AM by Rico Mariani

# re: Enumerating over arrays with for vs. foreach

Thanks for the notes! I thought it'd be too much for the JIT but just wondered if I was underestimating it :)

As for not using ArrayList, it was only an example :) But I usually write the above for value type collections to avoid the boxing penalty of System.ArrayList. As I said, no whidbey\generics as of yet :(

Thanks again,
n!
Tuesday, May 04, 2004 9:51 AM by nfactorial

# re: Enumerating over arrays with for vs. foreach

Gotcha :)
Tuesday, May 04, 2004 9:57 AM by Rico Mariani

# re: Enumerating over arrays with for vs. foreach

Hi again,
Sorry to come back to this :) I was thinking, is it possible to provide a hint to the JIT that a local count *is* in actual fact less than the length of the array. Thus avoiding the bounds check each time.

For instance, if I have a custom collection and within a collection method I need to scan the array:

public class MyCollection
{
private int count = 0;
private int[] itemList;

... yadda yadda ...

public bool Contains( int someValue )
{
for ( int loop = 0; loop < count; ++loop )
{
if ( itemList[ loop ] == someValue )
return true;
}

return false;
}
}

I will get the bounds check, would the JIT understand something like:

public bool Contains( int someValue )
{
if ( count > 0 && count <= itemList.Length )
{
for ( int loop = 0; loop < count; ++loop )
{
if ( itemList[ loop ] == someValue )
return true;
}
}

return false;
}

Although the first 'if' statement essentially does nothing (I know count is within this range), would the JIT take the hint? Again, please ignore the uselessness of this example :)
I'm thinking it doesn't (would be nice if it did), but could well be wrong :)

Thanks,
n!
Thursday, May 27, 2004 2:41 AM by nfactorial

# The Bum Wrap of foreach

Tuesday, June 29, 2004 11:33 PM by Brad Abrams

# The Bum Wrap of foreach

Wednesday, June 30, 2004 1:22 PM by dotRob

# The Bum Rap of foreach

Wednesday, June 30, 2004 4:57 PM by Brad Abrams

# re: Enumerating over arrays with for vs. foreach

I think it's same thing below.

Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();



for (int i=0; i<assemblies.Length; i++)

DoSomething(assemblies[i]);



foreach (Assembly a in assemblies)

DoSomething(a);
Thursday, July 01, 2004 1:59 AM by 仪表
New Comments to this post are disabled
 
Page view tracker