В процессе разработки на платформе 1С:Предприятие 8.3.17.1851 многие специалисты столкнулись с неожиданным поведением коллекции Соответствие. При обходе коллекции в цикле Для каждого порядок получения элементов стал отличаться от того, что наблюдалось на более ранних (8.3.10) или более поздних (8.3.18) версиях платформы. Особенно ярко это проявляется, когда количество элементов в коллекции превышает 9. Проанализируем, почему это происходит, является ли это ошибкой и как правильно организовать работу с данными, если важен порядок их следования.
Рассмотрим типовую ситуацию. Программист создает коллекцию Соответствие, наполняет ее данными, используя числовые ключи (например, номера строк), и ожидает, что при обходе коллекции элементы будут извлекаться либо в порядке добавления, либо по возрастанию ключа. Посмотрим на пример кода, который вызывает вопросы:
СведенияПоСерии = Новый Соответствие;
НомерСтроки = 1;
Для Н = 1 По 100 Цикл
СведенияПоСтроке = Новый Структура;
СведенияПоСтроке.Вставить("НомерСтроки", НомерСтроки);
СведенияПоСерии.Вставить(НомерСтроки, СведенияПоСтроке);
НомерСтроки = НомерСтроки + 1;
КонецЦикла;
Для Каждого Стр Из СведенияПоСерии Цикл
Выборка = Стр.Значение;
Сообщить(Выборка.НомерСтроки);
КонецЦикла;
На версии 8.3.17.1851 результат может начаться с цифры 9, затем пойти 65, а потом 1, 2, 3 и так далее. Это сбивает с толку, так как на других релизах порядок мог казаться "логичным". Однако, согласно официальной документации (Синтакс-Помощнику), объект Соответствие представляет собой неупорядоченную коллекцию значений. Порядок обхода итератором Для каждого в общем виде не определен.
Почему же поведение изменилось именно в версии 8.3.17? Разберем внутреннее устройство платформы. Коллекции Соответствие и Структура внутри реализованы как хеш-таблицы. Для быстрого поиска значения по ключу платформа вычисляет хеш-код ключа и определяет "корзину" (bucket), в которой будет храниться значение.
Проанализируем технические нюансы работы этих коллекций в 8.3.17:
Если логика вашего алгоритма зависит от последовательности элементов (например, при печати строк или формировании файла), использовать Соответствие напрямую для обхода нельзя. Рассмотрим альтернативные варианты решения задачи.
Если нам нужно быстро искать элемент по ключу и при этом сохранять порядок добавления, мы можем использовать связку из двух коллекций. Выясним, как это реализовать:
СведенияПоСерии = Новый Соответствие;
ПорядокКлючей = Новый Массив; // Здесь будем хранить ключи в нужном порядке
Для Н = 1 По 100 Цикл
НомерСтроки = Н;
СведенияПоСтроке = Новый Структура("НомерСтроки", НомерСтроки);
СведенияПоСерии.Вставить(НомерСтроки, СведенияПоСтроке);
ПорядокКлючей.Добавить(НомерСтроки); // Запоминаем порядок
КонецЦикла;
// Обход в гарантированном порядке
Для Каждого Ключ Из ПорядокКлючей Цикл
Выборка = СведенияПоСерии[Ключ];
Сообщить(Выборка.НомерСтроки);
КонецЦикла;
В данном примере Массив гарантирует нам последовательность 1, 2, 3..., а Соответствие обеспечивает мгновенный доступ к данным по ключу.
Если данные необходимо упорядочить не по времени добавления, а по значению одного из полей, лучше всего подойдет ТаблицаЗначений. Проанализируем этот способ:
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"));
ТаблицаДанных.Колонки.Добавить("Данные", Новый ОписаниеТипов("Структура"));
Для Н = 1 По 100 Цикл
НоваяСтр = ТаблицаДанных.Добавить();
НоваяСтр.НомерСтроки = Н;
НоваяСтр.Данные = Новый Структура("Значение", "Текст " + Н);
КонецЦикла;
// Явно задаем порядок перед обходом
ТаблицаДанных.Сортировать("НомерСтроки Возр");
Для Каждого Стр Из ТаблицаДанных Цикл
Сообщить(Стр.НомерСтроки);
КонецЦикла;
Использование метода Сортировать() делает ваш код устойчивым к любым изменениям платформы, так как порядок теперь определяется вашей бизнес-логикой, а не внутренним состоянием памяти 1С.
Для простых списков "ключ-значение", где требуется визуализация или выбор пользователем, отлично подходит СписокЗначений. Он всегда сохраняет порядок добавления и имеет встроенные методы сортировки.
Подведем итог нашему исследованию. Изменение поведения платформы 8.3.17.1851 в части перебора Соответствия не является программной ошибкой — это приведение работы системы к соответствию заявленной спецификации. Главное правило разработчика 1С: никогда не полагаться на порядок элементов в коллекциях Соответствие и Структура.
Чтобы ваш код работал стабильно на любых версиях платформы, следуйте этим рекомендациям:
Массив, если важна последовательность добавления.ТаблицаЗначений или СписокЗначений, если требуется сортировка.ВыборкаИзРезультатаЗапроса, так как она сохраняет порядок, указанный в секции УПОРЯДОЧИТЬ ПО.Соответствия в JSON или XML порядок ключей также может меняться от версии к версии, что критично для автоматизированных тестов.Соблюдение этих принципов позволит избежать трудноуловимых ошибок, которые проявляются только при обновлении платформы или увеличении объема данных у клиента.