Гарантирует ли цикл foreach в C # порядок вычисления? - PullRequest
23 голосов
/ 23 июня 2010

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

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

Ответы [ 4 ]

39 голосов
/ 23 июня 2010

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

Стандартные состояния (ECMA-334 §13.9.5):

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

11 голосов
/ 23 июня 2010

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

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

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

Таким образом, если базовая коллекция имеет четкий «первый» элемент, а каждый элемент имеет четкий «следующий» элемент, как в случае массивов, списков и т. Д., То можно ожидать, что foreach будет вести себя логически и стабильно. Если это что-то вроде набора, который не имеет первой или следующей последовательности, то он может вести себя нестабильно, хотя, предположительно, без изменения состояния IEnumerable, даже коллекции, которые не имеют определенного порядка, будут непротиворечивыми, поскольку их несогласованность будет более Работа!

5 голосов
/ 23 июня 2010

Что бы это ни стоило, вы можете найти многое из этого в Отражатель . В 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 голосов
/ 23 июня 2010

Предостережение на foreach - это хэш-массивы, в которых порядок не гарантируется из-за ... хеш-ключей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...