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

bad*_*nda 24 c# foreach

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

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

Mat*_*hen 39

对于数组(注意System.Array实现IEnumerable),它将按顺序访问元素.对于其他类型(IEnumerable或具有GetEnumerator),它通过交替MoveNextCurrent调用以所提供的顺序访问元素.

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

"foreach遍历数组元素的顺序如下:对于单维数组,元素以递增的索引顺序遍历,从索引0开始,以索引Length - 1结束.对于多维数组,元素是遍历,使得最右边的维度的索引首先增加,然后是下一个左维度,依此类推到左边."


Pet*_*ham 11

foreach是建立在顶部IEnumerable<T>的合同枚举的MSDN说:

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

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

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


Mar*_*ger 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;
}
Run Code Online (Sandbox Code Playgroud)

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


ddm*_*ddm 5

foreach 的警告是哈希数组,由于...哈希键,无法保证顺序。