При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда две структуры, содержащие абсолютно идентичные наборы ключей и значений, при сравнении через оператор = выдают результат Ложь. На первый взгляд это кажется нелогичным, особенно если в других языках программирования предусмотрены механизмы автоматического сравнения содержимого коллекций. В этой статье мы подробно разберем, почему так происходит, рассмотрим внутренние механизмы платформы и выясним, какие инструменты использовать для корректного сопоставления данных.
Проанализируем базовый принцип работы платформы с объектами. В 1С Структура является ссылочным типом данных. Когда мы создаем новую структуру с помощью конструктора Новый Структура, платформа выделяет под нее отдельную область в памяти. Оператор сравнения = для таких типов данных проверяет не содержимое объекта, а его адрес в памяти (указатель).
Рассмотрим пример кода, поясняющий эту логику:
Структура1 = Новый Структура("Поле1", 10);
Структура2 = Новый Структура("Поле1", 10);
Структура3 = Структура1;
// Результат будет Ложь, так как это разные объекты в памяти
Если Структура1 = Структура2 Тогда
Сообщить("Равны");
Иначе
Сообщить("Не равны");
КонецЕсли;
// Результат будет Истина, так как Структура3 указывает на тот же объект, что и Структура1
Если Структура1 = Структура3 Тогда
Сообщить("Равны");
КонецЕсли;
Таким образом, даже если мы наполним Структура1 и Структура2 одинаковыми данными, для платформы они останутся разными сущностями. Это правило справедливо для большинства коллекций значений: массивов, соответствий, таблиц значений и списков значений.
Если в вашей конфигурации используется БСП, нам не нужно изобретать велосипед. Разработчики фирмы «1С» уже предусмотрели специальные функции в модуле ОбщегоНазначения для сравнения коллекций по их содержимому.
Способ 1: Сравнение плоских структур
Для сравнения простых структур (где значениями являются примитивные типы: строка, число, дата, булево) отлично подходит функция:
ОбщегоНазначения.КоллекцииИдентичны(Коллекция1, Коллекция2)
Она последовательно перебирает элементы и проверяет их равенство.
Способ 2: Глубокое сравнение (рекурсивное)
Если внутри структуры могут находиться другие структуры, массивы или таблицы значений, обычного перебора ключей будет недостаточно. В этом случае проанализируем функцию:
ОбщегоНазначения.ДанныеСовпадают(Данные1, Данные2)
Эта функция выполняет рекурсивный обход всех вложенных элементов. Она поддерживает сравнение практически всех типов данных, включая ФиксированнаяСтруктура, Соответствие и даже ХранилищеЗначения.
Интересно рассмотреть ситуацию, упомянутую опытными разработчиками: в контексте Веб-клиента сравнение двух разных пустых структур может вернуть Истина. Это происходит из-за особенностей трансляции объектов 1С в JavaScript-объекты при передаче данных в браузер. В некоторых версиях платформы механизмы сериализации могут приводить к тому, что оператор = на клиенте начинает сравнивать значения, а не ссылки.
Важно: Никогда не полагайтесь на это поведение при разработке. Оно считается недокументированной особенностью реализации конкретного релиза и может измениться в любой момент. Всегда используйте явные методы сравнения, чтобы код работал стабильно и на сервере, и в тонком клиенте.
Выясним, существует ли универсальный способ сравнить две структуры «в лоб» без использования БСП. Один из популярных приемов — преобразование структур в строку формата JSON с последующим сравнением строк.
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Структура1);
Строка1 = ЗаписьJSON.Закрыть();
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Структура2);
Строка2 = ЗаписьJSON.Закрыть();
Если Строка1 = Строка2 Тогда
// Структуры идентичны
КонецЕсли;
Однако у этого метода есть критический «подводный камень»: порядок добавления ключей. В 1С структуры сохраняют порядок вставки элементов. Если в первую структуру вы сначала добавили «Имя», а потом «Фамилия», а во вторую — наоборот, то их JSON-представления будут отличаться, хотя логически наборы данных одинаковы. Поэтому данный метод можно использовать только в тех случаях, когда вы гарантируете идентичный порядок заполнения объектов.
Рассмотрим, как реализовать собственную функцию сравнения, если БСП недоступна. Нам необходимо выполнить следующие шаги:
Количество(). Если оно разное — структуры не равны.Свойство().Пример реализации простой функции:
Функция СтруктурыРавны(Стр1, Стр2) Экспорт
Если Стр1.Количество() <> Стр2.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Для Каждого Элемент Из Стр1 Цикл
ЗначениеВторой = Неопределено;
Если Не Стр2.Свойство(Элемент.Ключ, ЗначениеВторой) Тогда
Возврат Ложь; // Ключ не найден
КонецЕсли;
Если Элемент.Значение <> ЗначениеВторой Тогда
Возврат Ложь; // Значения отличаются
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Подводя итог нашему анализу, выделим основные правила работы со структурами:
Структура1 = Структура2 для проверки идентичности данных. Этот оператор проверяет только то, являются ли две переменные одним и тем же объектом в памяти.ОбщегоНазначения.ДанныеСовпадают — это самый надежный и универсальный способ, учитывающий вложенность и типы данных.Количество() — это позволит мгновенно отсеять заведомо разные объекты.Соблюдение этих принципов позволит избежать трудноуловимых ошибок в логике серверных процедур и обеспечит стабильную работу ваших механизмов проверки данных.