Является ли порядок объектов, возвращаемых FOREACH, стабильным? - PullRequest
19 голосов
/ 03 октября 2008

Можно ли предположить, что два итерации в одной коллекции возвращают объекты в одном и том же порядке? Очевидно, предполагается, что коллекция не изменилась иным образом.

Ответы [ 8 ]

25 голосов
/ 03 октября 2008

Зависит от типа коллекции. Для большинства коллекций ответ - «Да».

Однако это не гарантируется. Документы типа коллекции должны указывать, стоит ли это делать или нет, но, как и большинство, эта деталь обычно просматривается. Однако, если он нестабилен, было бы огромным недосмотром, если бы документы не упоминали об этом.

15 голосов
/ 03 октября 2008

Краткий ответ - да.

Очевидно, однако, что порядок элементов в коллекции может быть не таким, как они были вставлены, в зависимости от типа коллекции (например, словарь).

Но вы будете получать одни и те же результаты при каждой итерации по одной неизмененной коллекции с использованием цикла foreach.

10 голосов
/ 03 октября 2008

Вы не можете гарантировать это, если не знаете конкретную реализацию класса, который вы повторяете.

Коллекции, имеющие определенный порядок элементов (например, List<T>), будут перечисляться в стабильном порядке.

Для коллекций, в которых состояние объекта не изменяется, весьма вероятно, что элементы вернутся в том же порядке, например Dictionary<K,V>, хотя это не гарантируется спецификацией.

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

6 голосов
/ 03 октября 2008

В то время как ответ «да» для всех встроенных коллекций и, возможно, для любого класса вменяемых коллекций, в документации нет никаких ограничений, сформулированных для IEnumerable. Поэтому ничто не говорит нам о том, что каждая итерация должна быть стабильной.

Я мог бы представить следующий вариант использования:

foreach (int i in new Shuffler(1, 2, 3, 4, 5, 6, 7, 8, 9))
    Console.WriteLine(i);

Это вполне может быть реализовано как класс, который выдает различный порядок для каждой итерации.

Итак - если вы также хотите рассмотреть странные пограничные случаи, ответ должен быть « no ».

3 голосов
/ 03 октября 2008

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

Я вижу случай для класса коллекции, который специально предназначен для возврата элементов в случайном порядке, например.

Короче говоря, если вы не знаете внутреннюю реализацию класса коллекции, не ничего не говорит о заказе.

2 голосов
/ 27 апреля 2012

Linq для этой цели определяет интерфейс IOrderedEnumerable .

1 голос
/ 03 октября 2008

Re "unmodified" (ответ NM) - обратите внимание, что многие сложные контейнеры, такие как Dictionary, не гарантируют сохранение порядка. Иногда добавление элемента приводит к тому, что он появляется последним (создается впечатление, что порядок сохранен), а иногда это приводит к реорганизации внутренних сегментов, давая совершенно другой порядок.

Такие вещи, как SortedList <,> и т. Д., Очевидно, имеют свои собственные правила.

0 голосов
/ 03 октября 2008

Я бы сказал, что для большинства коллекций можно предположить это. Не исключено, что в определенной коллекции перечислитель может быть реализован недетерминированным образом, но этого, вероятно, не произойдет ...

...