Почему сравнение двух одинаковых структур в 1С возвращает Ложь?

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

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

Понятие сравнения «по значению» и «по ссылке»

Для того чтобы понять причину такого поведения системы, нам необходимо разделить все типы данных 1С на две большие группы по способу их сравнения. Рассмотрим их подробнее:

  1. Сравнение по значению: В этом случае платформа анализирует внутреннее содержимое переменной. Если содержимое совпадает, система возвращает Истина. К этой группе относятся все примитивные типы данных: Число, Строка, Дата, Булево. Также сюда входят системные перечисления и значения пустых ссылок.
  2. Сравнение по адресу (ссылке) в памяти: Здесь платформа не проверяет, что находится внутри объекта. Она лишь сравнивает адреса ячеек оперативной памяти, в которых расположены эти объекты. Если две переменные указывают на разные «коробки» с данными, они не будут равны, даже если содержимое этих коробок идентично.

Проанализируем пример из обсуждения. Когда мы пишем Новый Структура, операционная система выделяет в памяти конкретный блок для этого объекта. Когда мы пишем это выражение второй раз в той же строке, выделяется другой блок памяти. Оператор = сравнивает эти адреса, видит, что они разные, и закономерно возвращает Ложь.

Мутабельность объектов и ее влияние на логику

Ключевым термином в данном вопросе является мутабельность (изменчивость). Мутабельный тип данных — это тип, объект которого может изменить свое внутреннее состояние (содержимое), не меняя своего адреса в памяти. В 1С к мутабельным типам относятся почти все коллекции:

Поскольку эти объекты могут быть огромными и сложными, платформа в целях производительности сравнивает их только по ссылке. Представьте, если бы при сравнении двух таблиц значений с миллионом строк компьютер каждый раз перебирал бы все ячейки — это бы парализовало работу системы. Поэтому разработчики платформы заложили правило: мутабельные объекты равны только сами себе (когда обе переменные ссылаются на один и тот же экземпляр в памяти).

Исключения из правил: ОписаниеТипов, Цвет и Шрифт

В дискуссии на форуме возник важный вопрос: будет ли сравнение (Новый Цвет) = (Новый Цвет) также давать Ложь? Здесь кроется важная особенность платформы. Существует ряд типов, которые хоть и создаются конструктором Новый, но в идеологии 1С считаются значениями, а не объектами-контейнерами.

Выясним, какие типы сравниваются по значению, несмотря на использование конструктора:

Если мы выполним следующий код:


Цвет1 = Новый Цвет(255, 0, 0);
Цвет2 = Новый Цвет(255, 0, 0);
Сообщить(Цвет1 = Цвет2); // Вернет Истина

Платформа увидит, что параметры цвета идентичны, и вернет Истина. Это происходит потому, что данные типы являются имутабельными (неизменяемыми) после создания в рамках свойств объектов, и платформа оптимизирует их сравнение.

Работа с указателями и переменными

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


ПерваяСтруктура = Новый Структура; 
ВтораяСтруктура = ПерваяСтруктура; 
ВтораяСтруктура.Вставить("Ключ", "Значение"); 
Сообщить(ПерваяСтруктура = ВтораяСтруктура); // Вернет Истина

Проанализируем ситуацию по шагам. В первой строке мы создаем объект. Во второй строке мы не создаем копию структуры, а лишь заставляем переменную ВтораяСтруктура смотреть на тот же адрес памяти, что и ПерваяСтруктура. Теперь у нас две «метки», указывающие на одну и ту же «коробку». Когда мы меняем данные через вторую переменную, содержимое первой меняется автоматически, так как объект один. Естественно, сравнение таких переменных даст Истина.

Как правильно сравнивать содержимое коллекций?

Если перед нами стоит задача выяснить, одинаковы ли данные внутри двух разных структур, обычный оператор равенства нам не поможет. Нам нужно выполнить «глубокое сравнение».

Способ 1: Использование Библиотеки Стандартных Подсистем (БСП)

Если ваша конфигурация построена на БСП, разработчики уже позаботились о решении этой задачи. В составе общего модуля ОбщегоНазначения (или ОбщегоНазначенияКлиентСервер) существуют специальные функции:

Способ 2: Самостоятельная реализация

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


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

Сравнение объектов базы данных

Важно также упомянуть разницу между Ссылками и Объектами в контексте базы данных. Это часто путает разработчиков:

  1. СправочникСсылка: Это немутабельный тип. По сути, это просто уникальный идентификатор (GUID). Если вы получили две ссылки на один и тот же товар разными запросами, сравнение Ссылка1 = Ссылка2 всегда даст Истина.
  2. СправочникОбъект: Это мутабельный тип, содержащий данные из базы в оперативной памяти. Если вы дважды вызовете Ссылка.ПолучитьОбъект(), вы создадите два разных объекта в памяти. Сравнение Объект1 = Объект2 вернет Ложь, даже если это один и тот же элемент справочника.

Резюмируем: Для корректной работы в 1С всегда помните, что оператор = для сложных объектов (структур, массивов, таблиц) проверяет не «похожесть» данных, а физическое совпадение места хранения этих данных в памяти. Для сравнения именно содержимого всегда используйте специализированные функции обхода или методы БСП.

← На главную