Подтвердить что ты не робот

Поддерживает ли цикл foreach в С# порядок оценки?

Логично предположить, что цикл foreach в С# будет вычисляться в том же порядке, что и цикл увеличения. Экспериментально, это так. Однако на сайте MSDN такого подтверждения нет.

Это просто такой очевидный ответ, что они не думали размещать эту информацию на сайте? Или есть вероятность, что он будет вести себя хаотично?

4b9b3361

Ответ 1

Для массивов (обратите внимание, что System.Array реализует IEnumerable), он будет обращаться к элементам по порядку. Для других типов ( IEnumerable или GetEnumerator) он получает доступ к элементам в указанном порядке, чередуя MoveNext и Current.

Стандарт гласит (ECMA-334 §13.9.5):

"Порядок, в котором foreach пересекает элементы массива, выглядит следующим образом: Для одномерных массивов элементы пересекаются в порядке возрастания индекса, начиная с индекса 0 и заканчивая индексом Длина - 1. Для многомерных массивов элементы пройдено так, что индексы самого правого измерения сначала увеличиваются, затем следующего левого измерения и так далее влево ".

Ответ 2

foreach построен поверх IEnumerable<T> Контракт для счетчика на MSDN говорит

Изначально перечислитель помещается перед первым элементом в коллекции.... Поэтому вы должны вызвать MoveNext, чтобы перевести счетчик в первый элемент коллекции перед чтением значения Current.

Current возвращает тот же объект, пока не будет вызван MoveNext. MoveNext устанавливает текущее значение в следующий элемент.

Итак, если базовая коллекция имеет чистый "первый" элемент, и каждый элемент имеет четкий "следующий" элемент, как и в случае с массивами, списками и т.д., вы можете ожидать, что 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 - массивы хэшей, где порядок не гарантируется из-за... хеш-ключей.