English 中文(简体)
In what order does a C# for each loop iterate over a List<T>?
原标题:

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.

最佳回答

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

问题回答

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...

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.

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.

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

Lists seem to return the items in an order they are in the backing store--so if they are added to the list that way they ll be returned that way.

If your program depends on the ordering, you may want to sort it before traversing the list.

It s somewhat silly for linear searches--but if you need the order a certain way your best bet is make the items in that order.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签