每个循环的C#以什么顺序迭代List <t>?</t>

时间:2009-11-24 14:00:18

标签: c# foreach operator-precedence

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

我发现another question关于同一主题,但我觉得它不能满足我的问题。

有人说未定义任何订单。但正如其他人所说,它遍历数组的顺序是固定的(从0到长度-1)。 8.8.4 The foreach statement

还有人说,对于任何带有订单的标准类(例如List<T>)都是如此。我找不到任何文件来支持这一点。所以我知道它现在可能会起作用,但也许在下一个.NET版本中它会有所不同(即使它可能不太可能)。

我还没有运气看过List(t).Enumerator文档。

Another related question指出,对于Java,它在文档中特别提到:

  

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

我在C#文档中寻找类似的内容。

提前致谢。

编辑:感谢所有人的所有答案(令人惊讶的是我得到了如此多的回复)。我从所有答案中理解的是List<T>总是按照索引的顺序迭代。但我仍然希望看到明确的文件和平,说明这一点,类似于Java documentation on List

6 个答案:

答案 0 :(得分:93)

基本上由IEnumerator实现决定 - 但对于List<T>,它将始终按照列表的自然顺序进行,即与索引器的顺序相同:list[0],{ {1}},list[1]等。

我不相信它是明确记录的 - 至少,我没有找到这样的文件 - 但我认为你可以把它当作保证。对该顺序的任何更改都会毫无意义地破坏所有类型的代码。事实上,我会惊讶地看到list[2]的任何实施违反了这一点。不可否认,看到它具体记录下来会很高兴......

答案 1 :(得分:8)

在您的链接中,接受的答案在C# Language Specification Version 3.0, page 240中说明:

  

foreach遍历的顺序   数组的元素是   如下:对于一维数组   元素越来越多   索引顺序,从索引0开始   以索引长度结束 - 1.对于   多维数组,元素是   遍历了这样的指数   最右边的尺寸增加了   首先,然后是下一个左维,   等等到左边。下列   示例打印出a中的每个值   元素中的二维数组   顺序:

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();
  }
}
     

产生的输出如下:   1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9在示例中

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.

答案 2 :(得分:5)

List<T>枚举器的Microsoft Reference Source page中,明确指出迭代是从0到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();
}

希望它仍然与某人相关

答案 3 :(得分:4)

顺序由迭代器定义,迭代器用于使用foreach循环遍历数据集合。

如果您使用的是可索引的标准集合(例如List),那么它将遍历从索引0开始并向上移动的集合。

如果您需要控制排序,您可以控制implementing your own IEnumerable处理集合的迭代方式,也可以在执行foreach循环之前按照您希望的方式对列表进行排序。

这解释了Enumerator如何适用于通用列表。首先,当前元素未定义,并使用MoveNext到达下一个项目。

如果您阅读MoveNext,则表示它将从集合的第一个元素开始,然后从那里移动到下一个元素,直到它到达集合的末尾。

答案 4 :(得分:1)

列表似乎按照它们在后备存储中的顺序返回项目 - 所以如果它们以这种方式添加到列表中,它们将以这种方式返回。

如果您的程序取决于订购,您可能希望在遍历列表之前对其进行排序。

线性搜索有些愚蠢 - 但如果您需要某种方式订购,那么最好的选择就是按顺序制作商品。

答案 5 :(得分:1)

我只需要做一些类似于快速破解代码的事情,虽然它不能用于我试图做的事情但它为我重新排序列表。

使用LINQ更改顺序

         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