In what order does a C# for each loop iterate over a List<T>?

63,764

Solution 1

On Microsoft Reference Source page for List<T> Enumerator it is explicitly stated that the iteration is done from 0 to Length-1:

internal Enumerator(List<T> list) {
    this.list = list;
    index = 0;
    version = list._version;
    current = default(T);
}

public bool MoveNext() {

    List<T> localList = list;

    if (version == localList._version && ((uint)index < (uint)localList._size)) 
    {                                                     
        current = localList._items[index];                    
        index++;
        return true;
    }
    return MoveNextRare();
}

Hope it's still relevant for somebody

Solution 2

Basically it's up to the IEnumerator implementation - but for a List<T> it will always go in the natural order of the list, i.e. the same order as the indexer: list[0], list[1], list[2] etc.

I don't believe it's explicitly documented - at least, I haven't found such documentation - but I think you can treat it as guaranteed. Any change to that ordering would pointlessly break all kinds of code. In fact, I'd be surprised to see any implementation of IList<T> which disobeyed this. Admittedly it would be nice to see it specifically documented...

Solution 3

In your link, the accepted answer states in C# Language Specification Version 3.0, page 240:

The order in which foreach traverses the elements of an array, is as follows: For single-dimensional arrays elements are traversed in increasing index order, starting with index 0 and ending with index Length – 1. For multi-dimensional arrays, elements are traversed such that the indices of the rightmost dimension are increased first, then the next left dimension, and so on to the left. The following example prints out each value in a two-dimensional array, in element order:

using System;
class Test
{
  static void Main() {
      double[,] values = {
          {1.2, 2.3, 3.4, 4.5},
          {5.6, 6.7, 7.8, 8.9}
      };
      foreach (double elementValue in values)
          Console.Write("{0} ", elementValue);
      Console.WriteLine();
  }
}

The output produced is as follows: 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9 In the example

int[] numbers = { 1, 3, 5, 7, 9 };
foreach (var n in numbers) Console.WriteLine(n);
the type of n is inferred to be int, the element type of numbers.

Solution 4

The order is defined by the iterator being used to traverse a collection of data using a foreach loop.

If you are using a standard collection that is indexable (such as a List), then it will traverse the collection starting with index 0 and moving up.

If you need to control the ordering you can either control how the iteration of the collection is handled by implementing your own IEnumerable, or you can sort the list the way you want it before executing the foreach loop.

This explains how Enumerator works for generic List. At first the current element is undefined and uses MoveNext to get to the next item.

If you read MoveNext it indicates that it will start with the first element of the collection and from there move to the next one until it reaches the end of the collection.

Solution 5

I've just had to do something similar as a quick hack of code, though it didn't work for what I was trying to do it did reorder the list for me.

Using LINQ to change the order

         DataGridViewColumn[] gridColumns = new DataGridViewColumn[dataGridView1.Columns.Count];
         dataGridView1.Columns.CopyTo(gridColumns, 0); //This created a list of columns

         gridColumns = (from n in gridColumns
                        orderby n.DisplayIndex descending
                        select n).ToArray(); //This then changed the order based on the displayindex
Share:
63,764
Matthijs Wessels
Author by

Matthijs Wessels

Employed as a Software Development Engineer at Amazon. Studied Computer Science &amp; Engineering at the Eindhoven University of Technology. Interested in Algorithms, AI, Best Practises.

Updated on August 17, 2020

Comments

  • Matthijs Wessels
    Matthijs Wessels over 3 years

    I was wondering about the order that a foreach loop in C# loops through a System.Collections.Generic.List<T> object.

    I found another question about the same topic, but I do not feel that it answers my question to my satisfaction.

    Someone states that no order is defined. But as someone else states, the order it traverses an array is fixed (from 0 to Length-1). 8.8.4 The foreach statement

    It was also said that the same holds for any standard classes with an order (e.g. List<T>). I can not find any documentation to back that up. So for all I know it might work like that now, but maybe in the next .NET version it will be different (even though it might be unlikely).

    I have also looked at the List(t).Enumerator documentation without luck.

    Another related question states that for Java, it is specifically mentioned in the documentation:

    List.iterator()returns an iterator over the elements in this list in proper sequence."

    I am looking for something like that in the C# documentation.

    Thanks in advance.

    Edit: Thank you for all you for all your answers (amazing how fast I got so many replies). What I understand from all the answers is that List<T> does always iterate in the order of its indexing. But I still would like to see a clear peace of documentation stating this, similar to the Java documentation on List.

  • amirlol
    amirlol about 14 years
    I literally just checked for an answer 5 seconds ago, and was about to post something similar. You are too fast!
  • Matthijs Wessels
    Matthijs Wessels about 14 years
    Thanks for your replies. Is there some documentation that guarantees this?
  • Brendan Enrick
    Brendan Enrick about 14 years
    For an IList you certainly better follow that standard implementation. For some collections there isn't necessarily an obvious ordering of the items in the collection so it could be implemented differently.
  • Matthijs Wessels
    Matthijs Wessels about 14 years
    Yes, but this is for an array. Does it also automatically hold for the List<T> class?
  • amirlol
    amirlol about 14 years
    // Since we implement IEnumerable<T> // and the default iteration is top to bottom, // just return the object. from in source: msdn.microsoft.com/en-us/library/ee5kxzk0%28VS.80%29.aspx
  • Matthijs Wessels
    Matthijs Wessels about 14 years
    Thanks for the reply and addition (Everyone is answering so fast, I can barely keep up). I read that too. Maybe I'm just being a <word to specify someone who wants to be too precise>, but I feel that when they say "first element" they mean the first element that is going to be iterated, not the element that is first according to the order of the iterated class.
  • Jon Skeet
    Jon Skeet about 14 years
    @Michael G: I wouldn't rely on the MSDN example code as documentation though. I've seen too many appalling errors in it.
  • Matthijs Wessels
    Matthijs Wessels about 14 years
    There they implement an iterator for a stack. They make a default iterator returned by GetEnumerator() that goes from top to bottom and two explicit iterators returned by TopToBottom and BottomToTop. The comment you quote is used to indicate that TopToBottom just returns the same as GetEnumerator(). At least, that's how I read it.
  • Brendan Enrick
    Brendan Enrick about 14 years
    Well if it is that important that you're certain that it goes the way you expect, the best way is to do what I said and implement IEnumerable yourself.
  • Joel Mueller
    Joel Mueller about 14 years
    List<T> uses an array for its backing store. So yes.
  • Eric Lippert
    Eric Lippert about 14 years
    But that's an implementation detail. List<T> is not required to use an array as its backing store.
  • jason
    jason about 14 years
    @Matthijs Wessels: You read it correctly but Jon's point is that it shouldn't be considered gospel on the topic.
  • RCIX
    RCIX about 14 years
    I would like to point out the documentation for List<T> (nto the example code): "The List<(Of <(T>)>) class is the generic equivalent of the ArrayList class. It implements the IList<(Of <(T>)>) generic interface using an array whose size is dynamically increased as required." (emphasis mine)
  • Matthijs Wessels
    Matthijs Wessels about 14 years
    @Jason: I should have added '@Micheal', Jon's comment wasn't there yet when I start typing mine :).
  • Matthijs Wessels
    Matthijs Wessels about 14 years
    Hmm, I guess it always uses an array then. But still, does that mean it cannot return a reversed enumerator?
  • Matthijs Wessels
    Matthijs Wessels about 11 years
    I don't see how this relates to the question. Your code doesn't even use a List. I think you misunderstood what I meant with "list".
  • Matthijs Wessels
    Matthijs Wessels about 11 years
    Also, why are you copying the content of Columns to gridColumns first? I think that you could also just do: DataGridViewColumn[] gridColumns = dataGridView1.Columns.OrderByDescending(n => n.DisplayIndex).ToArray();
  • Austin Henley
    Austin Henley about 11 years
    @MatthijsWessels It wouldn't be hard to change that to use List, if you wanted.
  • Matthijs Wessels
    Matthijs Wessels about 11 years
    @AustinHenley You could do a foreach on the IOrderedEnumerable, but that's not what the question is about. You could also do to ToList instead of ToArray, but then you just have a List again and the question whether a foreach will then loop over the items in the specified order is still unanswered.
  • yazanpro
    yazanpro almost 11 years
    can anybody please provide the same answer regarding the array?
  • Jon Skeet
    Jon Skeet almost 11 years
    @yazanpro: foreach will definitely iterate in order with an array.
  • flyinryan
    flyinryan about 2 years
    It's never too late for a better answer , and it can't get any better than this one.
  • Avi
    Avi about 2 years
    OMG. This is exactly the purpose for which I was looking for this code. Thanks so much!!!!