每个循环的 C # 以什么顺序遍历 List < T > ?

我想知道 C # 中 foreach 循环通过 System.Collections.Generic.List<T>对象的顺序。

我发现 另一个问题是关于同一个主题的,但是我觉得它并没有给我满意的答案。

有人声明没有定义顺序。但是正如其他人所说,它遍历数组的顺序是固定的(从0到 Llength-1)。8.8.4 foreach 语句

还有人说,对于任何带有订单的标准类(例如 List<T>)也是如此。我找不到任何文件来证明这一点。所以就我所知,现在可能是这样,但也许下一次就是了。NET 版本会有所不同(尽管可能不太可能)。

我还查看了 List(t).Enumerator文档,但没有找到。

另一个相关的问题 指出,对于 Java,文档中特别提到:

List.iterator()返回此列表中元素的迭代器 按照正确的顺序

我正在 C # 文档中寻找类似的东西。

先谢谢你。

编辑: 谢谢你们所有人的回答(我很惊讶这么快就收到了这么多的回复)。我从所有的答案中了解到的是,List<T>总是按照它的索引顺序进行迭代。但我仍然希望看到一个明确的和平的文档说明这一点,类似于 关于 List的 Java 文档

68320 次浏览

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

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.

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.

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.

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

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