views:

520

answers:

3

A coworker used a for loop to iterate a List in some C# code he wrote and left the comment, "did't use For Each because I wasn't sure it iterates in order. Who knows what Microsoft will do." For example, suppose we have a List built up like this:

var someList = new List<string>();

someList.Add("one");
someList.Add("two");
someList.Add("three");

my coworker used something like this:

for (int i = 0; i < someList.Count; i++)    
{
    System.Diagnostics.Debug.WriteLine(someList[i]);
}

instead of this:

foreach (var item in someList)              
{
    System.Diagnostics.Debug.WriteLine(item);
}

I guess he's afraid the items might come out in a different order than they were added to the collection. I think he's being a bit paranoid, but technically, the documentation does not state the order in which the collection is iterated. Is it possible for a foreach statement to traverse an array or collection object in any order other than from lowest bound to highest?

+16  A: 

Your question is regarding a List<T>, which does maintain order.

foreach, alone, is not guaranteed to do anything. It just asks the object provided for its enumerator, which could do anything, potentially.

Rex M
+1 Oh no, the Skeet effect has you getting fewer votes.
Chris Ballance
Testing to see whether I can overcome the Skeet effect. Fingers crossed.
Rex M
You've currently got one more than me due to my own upvote. I assume that isn't the Skeet effect you meant ;)
Jon Skeet
Thanks. I didn't dig deep enough into the documentation: http://msdn.microsoft.com/en-us/library/aa288257(VS.71).aspx
raven
+11  A: 

It depends on the collection:

  • For List<T> it's guaranteed to be insertion order. (That's assuming just Add calls as shown. If you insert elements into the list at particular places, they'd get returned at the right pointas you'd expect.) Basically it's the same order as you'd get by taking list[0], list[1], list[2] etc.
  • For Dictionary<TKey, TValue> there's no guaranteed ordering.
  • For SortedList<TKey, TValue> (and the like) it'll be in key comparison order - that's the point of the type.
  • Arrays always come out in element order.
Jon Skeet
Although you're correct, I would still argue that foreach is ONLY for iterating through all the objects in a collection, and in no way guarantees any order. It is up to the collection implementation to determine the order that foreach will select. So using foreach has no guaranteed behaviour.
@devinb I think that's kind of what @Jon is saying.
Rex M
Well, foreach is guaranteed to use GetEnumerator from the collection - so if you know the collection's iterator's order, you are guaranteed the same order from foreach. It's entirely reasonable to rely on it iterating over a List in order, for example.
Jon Skeet
@Rex I suppose I wasn't clear. I was trying to say that the order of a foreach should be considered a side effect. Whereas a for loop has a guaranteed order. Jon glossed over that fact and implied that foreach should be used. I feel that if an indexed order is essential, then a for loop is safer.
@both: Ha... well, now I just look foolish. I'll leave my comments here for posterity though, so that it doesn't look like you guys were responding to nothing.
+4  A: 

To specifically answer the question, "foreach" returns the order that the .GetEnumerator() returns. For lists, it's the order that you added things to the end. For dictionaries, it's probably the order of the buckets where things were assigned.

Jeff Moser