Почему не получается сравнить две структуры в 1С через знак равенства и как это сделать правильно?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда две структуры, содержащие абсолютно идентичные наборы ключей и значений, при сравнении через оператор = выдают результат Ложь. На первый взгляд это кажется нелогичным, особенно если в других языках программирования предусмотрены механизмы автоматического сравнения содержимого коллекций. В этой статье мы подробно разберем, почему так происходит, рассмотрим внутренние механизмы платформы и выясним, какие инструменты использовать для корректного сопоставления данных.

Причина №1: Ссылочная природа объектов

Проанализируем базовый принцип работы платформы с объектами. В 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(ЗаписьJSON, Структура1);
Строка1 = ЗаписьJSON.Закрыть();

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Структура2);
Строка2 = ЗаписьJSON.Закрыть();

Если Строка1 = Строка2 Тогда
    // Структуры идентичны
КонецЕсли;

Однако у этого метода есть критический «подводный камень»: порядок добавления ключей. В 1С структуры сохраняют порядок вставки элементов. Если в первую структуру вы сначала добавили «Имя», а потом «Фамилия», а во вторую — наоборот, то их JSON-представления будут отличаться, хотя логически наборы данных одинаковы. Поэтому данный метод можно использовать только в тех случаях, когда вы гарантируете идентичный порядок заполнения объектов.

Алгоритм ручного сравнения структур

Рассмотрим, как реализовать собственную функцию сравнения, если БСП недоступна. Нам необходимо выполнить следующие шаги:

  1. Проверить равенство количества элементов через свойство Количество(). Если оно разное — структуры не равны.
  2. Перебрать все ключи первой структуры.
  3. Проверить наличие аналогичного ключа во второй структуре с помощью метода Свойство().
  4. Сравнить значения по каждому ключу.

Пример реализации простой функции:


Функция СтруктурыРавны(Стр1, Стр2) Экспорт
    Если Стр1.Количество() <> Стр2.Количество() Тогда
        Возврат Ложь;
    КонецЕсли;
    
    Для Каждого Элемент Из Стр1 Цикл
        ЗначениеВторой = Неопределено;
        Если Не Стр2.Свойство(Элемент.Ключ, ЗначениеВторой) Тогда
            Возврат Ложь; // Ключ не найден
        КонецЕсли;
        
        Если Элемент.Значение <> ЗначениеВторой Тогда
            Возврат Ложь; // Значения отличаются
        КонецЕсли;
    КонецЦикла;
    
    Возврат Истина;
КонецФункции

Итоги и рекомендации

Подводя итог нашему анализу, выделим основные правила работы со структурами:

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

← На главную