Логически, можно было бы думать, что цикл foreach в C# оценит в том же порядке как постепенное увеличение для цикла. Экспериментально, это делает. Однако на сайте MSDN, кажется, нет такого подтверждения.
Это - просто такой очевидный ответ, что они не думали для включения той информации о сайте? Или есть ли возможность, что это будет вести себя беспорядочно?
Для массивов (обратите внимание, что System.Array
реализует IEnumerable
), он будет обращаться к элементам по порядку. Для других типов ( IEnumerable
или имеющих GetEnumerator
) он обращается к элементам в указанном порядке посредством чередующихся вызовов MoveNext
и Current
.
Стандартные состояния (ECMA-334 §13.9.5):
«Порядок, в котором проходит foreach элементы массива, как следующим образом: Для одномерных массивов элементы пересекаются при увеличении порядок индекса, начиная с индекса 0 и оканчивается индексом Длина - 1. Для многомерные массивы, элементы пройдено так, что индексы крайнее правое измерение увеличено сначала, затем следующее левое измерение, и так далее влево ».
Что бы это ни стоило, вы можете многое найти в 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;
}
Это, очевидно, один пример, но ответ таков: это зависит от разработчика, и вы можете узнать большую часть того, как они работают, экспериментально или проверив исходный код. , в некоторых случаях.
Предостережью на каждый раз являются хэш-массивы, где порядок не гарантируется из-за ... хэш-ключи.
foreach
построен поверх IEnumerable
В контракте для счетчика на MSDN указано
Изначально перечислитель располагается перед первым элементом в Коллекция. ... Следовательно, вы должны вызвать MoveNext, чтобы переместить перечислитель к первому элементу коллекции перед чтением значения Current.
Current возвращает тот же объект, пока не будет вызван MoveNext. MoveNext устанавливает Current для следующего элемента.
Таким образом, если в базовой коллекции есть чистый «первый» элемент, и каждый элемент имеет четкий «следующий» элемент, как в случае с массивами, списками и т. Д., Тогда вы можете ожидать, что foreach
вести себя логично и стабильно. Если это что-то вроде набора, у которого нет ни первой, ни следующей последовательности, тогда он может вести себя нестабильно, хотя, предположительно, без изменения состояния IEnumerable даже коллекции, которые не имеют определенного порядка, будут согласованными, поскольку их несогласованность будет более серьезной. Работа!