逻辑上,人们会认为C#中的foreach循环将以与递增for循环相同的顺序进行求值。实验上,确实如此。但是,MSDN网站上似乎没有此类确认。
它是否只是一个明显的答案,他们不认为在网站上包含这些信息?或者它是否有可能表现不正常?
答案 0 :(得分:39)
对于数组(请注意System.Array
实现IEnumerable
),它将按顺序访问元素。对于其他类型(IEnumerable
或GetEnumerator
),它会通过交替MoveNext
和Current
调用来按所提供的顺序访问元素。
标准状态(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,由于...哈希键,无法保证顺序。