C#中的foreach循环是否保证评估顺序?

时间:2010-06-22 23:01:29

标签: c# foreach

逻辑上,人们会认为C#中的foreach循环将以与递增for循环相同的顺序进行求值。实验上,确实如此。但是,MSDN网站上似乎没有此类确认。

它是否只是一个明显的答案,他们不认为在网站上包含这些信息?或者它是否有可能表现不正常?

4 个答案:

答案 0 :(得分:39)

对于数组(请注意System.Array实现IEnumerable),它将按顺序访问元素。对于其他类型(IEnumerableGetEnumerator),它会通过交替MoveNextCurrent调用来按所提供的顺序访问元素。

标准状态(ECMA-334§13.9.5):

  

“foreach遍历的顺序   数组的元素是   如下:对于一维数组   元素越来越多   索引顺序,从索引0开始   以索引长度结束 - 1.对于   多维数组,元素是   遍历了这样的指数   最右边的尺寸增加了   首先,然后是下一个左维,   等等在左边。“

答案 1 :(得分:11)

foreach建立在IEnumerable<T>之上MSDN上的调查员合同

  

最初,枚举数位于集合中的第一个元素之前。 ...因此,在读取Current的值之前,必须调用MoveNext将枚举数推进到集合的第一个元素。

     

Current返回相同的对象,直到调用MoveNext。 MoveNext将Current设置为下一个元素。

因此,如果底层集合具有明确的'first'元素,并且每个元素都有一个明确的'next'元素,就像数组,列表等那样,那么你可以期望foreach到行为逻辑和稳定。如果它类似于一个没有第一个或下一个序列的集合,那么它可能会以不稳定的方式运行,尽管可能没有改变IEnumerable的状态,即使没有定义顺序的集合也会保持一致,因为它们不一致会更多工作!

答案 2 :(得分:5)

对于它的价值,你可以在Reflector中查找很多内容。在mscorlib中,System.Array实现IEnumerable(如上所述),Array#GetEnumerator返回ArrayEnumerator。这是ArrayEnumerator#MoveNext的主体:

public bool MoveNext()
{
    if (this._complete)
    {
        this.index = this.endIndex;
        return false;
    }
    this.index++;
    this.IncArray();
    return !this._complete;
}

这显然是一个例子,但答案是:这取决于实施者,你可以找到他们实验工作的大部分方式,或者在某些情况下检查来源。

答案 3 :(得分:3)

对foreach的警告是Hash Arrays,由于...哈希键,无法保证顺序。