【问题标题】:Does the foreach loop in C# guarantee an order of evaluation?C# 中的 foreach 循环是否保证评估顺序?
【发布时间】:2010-06-22 23:01:28
【问题描述】:

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

是否只是一个如此明显的答案,以至于他们没有考虑在网站上包含该信息?还是有可能会出现异常行为?

【问题讨论】:

    标签: c# foreach


    【解决方案1】:

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

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

    "foreach遍历的顺序 数组的元素,如 如下:对于一维数组 元素以递增方式遍历 索引顺序,从索引 0 开始, 以索引长度结尾 - 1。对于 多维数组,元素是 遍历使得 最右边的维度增加了 首先,然后是下一个左侧维度, 以此类推。”

    【讨论】:

      【解决方案2】:

      foreach 是建立在 IEnumerable<T> 之上的 MSDN 上的枚举数合同说

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

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

      因此,如果基础集合具有明确的“第一个”元素,并且每个元素都有一个明确的“下一个”元素,就像数组、列表等的情况一样,那么您可以期望 foreach 的行为符合逻辑并且稳定。如果它是一个集合之类的东西,没有第一个或下一个序列,那么它可能会以不稳定的方式运行,尽管可能在不改变 IEnumerable 的状态的情况下,即使没有定义顺序的集合也是一致的,因为使它们不一致会更多工作!

      【讨论】:

        【解决方案3】:

        对于它的价值,您可以在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;
        }
        

        这显然是一个例子,但答案是:这取决于实施者,在某些情况下,您可以通过实验或检查源代码来了解它们的大部分工作方式。

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            猜你喜欢
            • 2013-10-18
            • 2018-11-20
            • 2011-08-30
            • 2016-05-02
            • 2013-07-06
            • 1970-01-01
            • 2016-11-24
            • 1970-01-01
            • 2020-04-09
            相关资源
            最近更新 更多