Разработка и Конфигурация · 13 мин
Соответствие и Структура в 1С: в чём разница и что выбрать
Разбираем отличия Соответствия от Структуры в 1С: типы ключей, производительность, сериализация, перебор элементов. Примеры кода и критерии выбора.
Структура и Соответствие во встроенном языке 1С решают похожую задачу — хранение наборов пар «ключ-значение», — но устроены по-разному и ведут себя неодинаково. Разработчик, который выбирает между ними «наугад», рано или поздно сталкивается с ошибками обращения к ключам, потерей данных при передаче между клиентом и сервером или лишними тормозами на больших объёмах.
Главное отличие в двух словах: Структура — это объект с фиксированным набором именованных свойств, к которым можно обращаться через точку, а Соответствие — это полноценная хеш-таблица, где ключом может быть значение любого типа. Из этого фундаментального различия вытекают все остальные: скорость поиска, правила сериализации, поведение при переборе и ограничения на имена ключей.
Ниже разберём устройство обоих типов, сравним их по практическим критериям, покажем типовые сценарии, где один вариант явно лучше другого, и разберём ошибки, которые чаще всего допускают при работе с этими коллекциями.
Что такое Структура и как она устроена
Структура — это коллекция пар «ключ-значение», где ключ всегда является строкой и должен удовлетворять правилам именования переменных встроенного языка: без пробелов, без спецсимволов, не может начинаться с цифры. Создаётся конструктором Новый Структура("Ключ1, Ключ2", Значение1, Значение2), а обратиться к значению можно двумя способами: через точку (Структура.Ключ1) или через квадратные скобки (Структура["Ключ1"]).
Обращение через точку делает код читаемым и похожим на работу с объектами конфигурации — именно поэтому Структуру повсеместно используют для передачи параметров в процедуры и функции, для возврата нескольких значений из функции, для группировки настроек. Метод Свойство("Имя", НайденноеЗначение) позволяет безопасно проверить наличие ключа, не вызывая исключения.
Важная особенность: Структура передаётся по ссылке. Если вы передали её в процедуру и там изменили — изменения видны в вызывающем коде. То же справедливо и для Соответствия. Это частый источник трудноуловимых ошибок, когда «внезапно» меняются данные, которые разработчик считал неизменными.
Что такое Соответствие и в чём его особенность
Соответствие — это коллекция, где ключом может выступать значение произвольного типа: строка, число, дата, ссылка на объект базы данных, другой объект. Создаётся без параметров: Новый Соответствие, элементы добавляются через Соответствие.Вставить(Ключ, Значение) или присваиванием Соответствие[Ключ] = Значение.
Внутренне Соответствие реализовано как хеш-таблица, поэтому поиск по ключу выполняется очень быстро — время поиска практически не зависит от количества элементов. Это делает Соответствие идеальным инструментом для построения индексов: например, когда нужно быстро находить строки таблицы значений по значению колонки или кэшировать результаты запросов по ссылкам.
Обращение к несуществующему ключу Соответствия не вызывает ошибку — возвращается Неопределено. Это одновременно удобно и опасно: опечатка в ключе не приведёт к исключению, а тихо вернёт пустое значение, и логика отработает неверно без каких-либо сообщений.
Ключевые отличия: сравнительная таблица
Соберём основные различия в одну таблицу — по ней удобно принимать решение в конкретной задаче.
| Критерий | Структура | Соответствие |
|---|---|---|
| Тип ключа | Только строка-идентификатор | Любой тип, включая ссылки и объекты |
| Обращение через точку | Да | Нет, только через скобки |
| Поиск по ключу | Быстрый, но на больших объёмах уступает хеш-таблице | Очень быстрый (хеш-таблица) |
| Несуществующий ключ | Исключение при прямом обращении | Возвращает Неопределено |
| Сериализация (XDTO, JSON) | Поддерживается, ключи — строки | Ограничена, ключи сложных типов не сериализуются |
| Передача клиент-сервер | Передаётся целиком | Передаётся, но есть нюансы с типами ключей |
| Фиксированная версия | ФиксированнаяСтруктура | ФиксированноеСоответствие |
| Типичное применение | Параметры, настройки, возврат значений | Кэши, индексы, сопоставление данных |
Из таблицы видно главное правило: если ключи — это осмысленные имена полей, известные на этапе написания кода, берите Структуру. Если ключи — это данные (ссылки, коды, даты), по которым нужно искать, — берите Соответствие.
Ключи: строки-идентификаторы против значений любого типа
Ограничение Структуры на строковые ключи-идентификаторы — не случайность, а следствие её природы: она эмулирует объект с именованными свойствами. Ключ «Код товара» с пробелом в Структуре создать нельзя — конструктор выдаст ошибку. А в Соответствии такой ключ допустим, равно как и ключ-ссылка на элемент справочника.
Возможность использовать ссылку как ключ — киллер-фича Соответствия. Классический сценарий: нужно сопоставить элементам справочника рассчитанные значения. Код вида Кэш.Вставить(ТоварСсылка, Остаток) работает напрямую, без преобразования ссылки в строку и обратно. Со Структурой пришлось бы изобретать строковое представление ссылки, что и медленнее, и чревато коллизиями.
Обратная сторона: поскольку ключи Соответствия могут быть любыми, платформа не может гарантировать их сериализацию. Структура со строковыми ключами корректно преобразуется в JSON и обратно штатными средствами, а Соответствие со ссылочными ключами при выгрузке в JSON потребует ручной обработки.
Производительность и работа с большими объёмами
На небольших коллекциях (десятки элементов) разница в скорости между Структурой и Соответствием практически незаметна. Различия проявляются, когда коллекция содержит тысячи и десятки тысяч элементов, а обращений к ней — сотни тысяч в цикле.
Соответствие как хеш-таблица обеспечивает почти постоянное время поиска независимо от размера. Поэтому для задач вида «найти строку таблицы значений по ключу в цикле» правильный паттерн такой: один раз построить Соответствие-индекс, а затем искать в нём. Линейный поиск методом Найти() по таблице значений внутри цикла — классическая причина «висящих» обработок, и замена его на Соответствие ускоряет код на порядки.
Структуру для таких индексов использовать не стоит: даже если ключи удаётся привести к строкам, на больших объёмах она проигрывает Соответствию, а код с экранированием ключей становится хрупким.
- 1Пройдите один раз по таблице значений или выборке запроса
- 2Для каждой строки выполните Индекс.Вставить(ЗначениеКлюча, СтрокаДанных)
- 3Если ключ не уникален, храните в значении массив строк и добавляйте в него
- 4В основном цикле обращайтесь к индексу: Результат = Индекс[Ключ]
- 5Проверяйте Результат на Неопределено перед использованием
Сериализация, JSON и передача между клиентом и сервером
Структура — стандартный контейнер для обмена данными с внешними системами. Штатная запись JSON через ЗаписатьJSON корректно обрабатывает Структуру: ключи становятся именами полей объекта, значения — значениями полей. При чтении JSON метод ПрочитатьJSON(Чтение, Истина) по умолчанию возвращает именно Соответствие, но с параметром можно получить и Структуру —
Соответствие в JSON сериализуется как массив пар или требует ручного обхода, а ключи сложных типов (ссылки, даты в нестандартном виде) придётся преобразовывать вручную. Поэтому для HTTP-API и обменов почти всегда выбирают Структуру.
При передаче между клиентом и сервером обе коллекции передаваемы, но есть нюанс: в фиксированных (немутирующих) вариантах — ФиксированнаяСтруктура и ФиксированноеСоответствие — данные кэшируются платформой и не передаются повторно при каждом вызове. Это стандартный способ хранения кэша на клиенте в управляемых формах.
Типичные сценарии выбора
Когда брать Структуру
Передача параметров в процедуру, когда их больше трёх-четырёх: вместо длинной сигнатуры — один параметр Параметры типа Структура. Возврат нескольких значений из функции. Хранение настроек обработки с понятными именами. Подготовка данных для JSON-запроса к внешнему API. Во всех этих случаях читаемость кода через обращение по точке перевешивает всё остальное.
Когда брать Соответствие
Кэширование результатов запросов по ссылкам внутри длительной обработки. Построение индексов для быстрого поиска строк таблицы значений. Подсчёт статистики по произвольным ключам (например, количество документов по контрагентам). Сопоставление данных из двух источников, где связующее поле — ссылка или составной ключ. Здесь решают скорость поиска и свобода в выборе типа ключа.
Когда не подходит ни то, ни другое
Если нужен упорядоченный набор значений без ключей — используйте Массив или СписокЗначений. Если нужна табличная структура с несколькими колонками и отборами — ТаблицаЗначений. Попытки эмулировать таблицу через «массив структур» работают, но лишают вас отборов, свёртки и итогов, которые таблица значений даёт из коробки.
Сравнение вариантов
Параметры, настройки, JSON-обмен. Ограничение: ключи только строки-идентификаторы.
Кэши, индексы, сопоставления по ссылкам. Ограничение: сложная сериализация, тихий возврат Неопределено.
Многоколоночные данные с отборами и итогами. Ограничение: тяжелее, поиск без индекса линейный.
Упорядоченный список без ключей. Ограничение: поиск только перебором.
Частые ошибки при работе с обеими коллекциями
Самая распространённая ошибка со Структурой — обращение к несуществующему ключу через точку. В отличие от Соответствия, это вызывает исключение «Поле объекта не обнаружено». Перед обращением к необязательному ключу используйте Структура.Свойство("Ключ", Значение) — метод вернёт Истина или Ложь и заполнит значение.
Зеркальная ошибка с Соответствием — забыть, что обращение к отсутствующему ключу молча возвращает Неопределено. Если дальше это значение передаётся в запрос или арифметику, ошибка всплывёт далеко от места причины. После получения значения из Соответствия делайте явную проверку на Неопределено, если отсутствие ключа — нештатная ситуация.
Ещё одна группа ошибок связана с изменением коллекции во время её перебора в цикле Для Каждого.. Из.. Цикл. Удаление или добавление элементов внутри такого цикла приводит к непредсказуемому поведению. Если нужно удалить часть элементов, сначала соберите их ключи в отдельный массив, а удаляйте уже после завершения перебора.
Как проверить корректность выбора и кода
После выбора типа коллекции полезно прогнать простые проверки. Убедитесь, что все ключи Структуры задокументированы в комментарии к процедуре-приёмнику — иначе через месяц никто не вспомнит, какие поля обязательны. Для Соответствия проверьте уникальность ключей на этапе заполнения: повторная вставка по существующему ключу молча перезапишет значение, и если это не intended-поведение, данные будут потеряны.
Для оценки производительности не гадайте — замеряйте. Оберните проблемный участок в замер через ТекущаяУниверсальнаяДатаВМиллисекундах() до и после замены линейного поиска на Соответствие. На реальных объёмах разница обычно видна сразу и служит лучшим аргументом за рефакторинг.
Как проверить результат
Используется Свойство() или проверка на Неопределено
Прямое обращение через точку или скобки без проверки
Индекс на Соответствии, построенный один раз
Метод Найти() по таблице внутри цикла
Повторная вставка по ключу обработана явно
Значения молча перезаписываются
Побочные изменения задокументированы или исключены
Вызывающий код не ожидает изменения коллекции
Что важно запомнить
Структура — именованные свойства со строковыми ключами, обращение через точку, идеальна для параметров и JSON. Соответствие — хеш-таблица с ключами любого типа и быстрым поиском, выбор для кэшей и индексов. Обе передаются по ссылке: контролируйте побочные изменения.
Частые вопросы
Можно ли использовать Структуру с ключами, содержащими русские буквы?
Да, кириллические идентификаторы допустимы: встроенный язык 1С полностью поддерживает русские имена переменных, и ключи Структуры подчиняются тем же правилам. Ключи вида «Номенклатура» или «СуммаДокумента» работают без ограничений. Недопустимы пробелы, дефисы и начало с цифры.
Что вернёт обращение к несуществующему ключу в каждой из коллекций?
Соответствие вернёт Неопределено без ошибки. Структура при обращении через точку или скобки вызовет исключение «Поле объекта не обнаружено». Безопасный способ для Структуры — метод Свойство("ИмяКлюча", Переменная), который возвращает Истина или Ложь и не генерирует исключение.
Что быстрее при большом количестве элементов?
Соответствие. Оно реализовано как хеш-таблица, и время поиска по ключу почти не зависит от числа элементов. На коллекциях в десятки тысяч записей и массовых обращениях в циклах разница становится существенной. Для небольших наборов параметров разница не ощущается, и выбирать стоит по удобству кода.
Можно ли передать Соответствие с клиента на сервер?
Да, Соответствие является передаваемым типом и допустимо в параметрах серверных вызовов. Однако для кэша на клиенте в управляемых формах чаще применяют ФиксированноеСоответствие: платформа кэширует его и не передаёт повторно при каждом серверном вызове, что снижает трафик.
Как выгрузить Соответствие со ссылочными ключами в JSON?
Штатной прямой сериализации для таких ключей нет. Практичный вариант — обойти Соответствие циклом и сформировать массив структур, где ссылка преобразована в строковое представление (например, через ЗначениеВСтрокуВнутр или уникальный идентификатор), а затем записать этот массив в JSON стандартным ЗаписатьJSON.
Чем ФиксированнаяСтруктура отличается от обычной?
ФиксированнаяСтруктура создаётся на основе обычной и после создания неизменяема: добавить или удалить ключи нельзя, попытка вызовет ошибку. Она используется для защиты данных от случайного изменения и для клиентского кэша в управляемых формах, поскольку платформа оптимизирует её передачу между клиентом и сервером.