Разработка и Конфигурация · 14 мин
Как сравнивать объекты в 1С
Как правильно сравнивать объекты в 1С: операторы сравнения, сравнение ссылок, строк и дат, типовые ошибки и проверка результата на практике.
Сравнение объектов — одна из самых частых операций в коде 1С: проверка товара в условии, поиск нужного контрагента, фильтрация строк таблицы, контроль заполнения реквизитов. При этом именно сравнение регулярно становится источником трудноуловимых ошибок: условие «вроде бы верное», но не срабатывает, потому что сравниваются ссылка и строка, разные типы данных или значения с лишними пробелами.
В языке 1С сравнение устроено иначе, чем во многих других языках: нет разделения на «==» и «===», примитивные значения сравниваются по содержимому, а ссылочные объекты — по идентичности ссылки. Понимание этих правил позволяет писать условия, которые работают предсказуемо, и быстро находить причины, когда сравнение «не видит» очевидно равные значения.
Ниже разобраны базовые операторы сравнения, особенности работы со ссылками, строками, датами и типами, а также типичные ошибки и способы их диагностики. Материал применим как во встроенном языке конфигураций на управляемых формах, так и в обычных приложениях.
Какие операторы сравнения есть во встроенном языке 1С
Во встроенном языке 1С доступен стандартный набор операторов: равно (=), не равно (<>), больше (>), меньше (<), больше или равно (>=), меньше или равно (<=). В отличие от C-подобных языков, для проверки равенства используется одинарный знак «=» — и в условии, и при присваивании. Контекст определяет, что именно делает оператор, поэтому перепутать их сложно, но новичкам стоит обратить на это внимание.
Результат любого сравнения — значение типа Булево (Истина или Ложь), которое можно использовать в конструкциях Если ... Тогда, Пока, тернарной логике через ?(Условие, Значение1, Значение2) и в запросах. Сравнение работает и в выражениях на языке запросов, но там синтаксис и поведение имеют свои особенности, например при работе с NULL.
Пример базового сравнения в коде:
Если Количество > 0 Тогда
Сообщить("Товар в наличии");
КонецЕсли;
Если Статус = Перечисления.СтатусыЗаказа.Выполнен Тогда
// действия для выполненного заказа
КонецЕсли;
Важно помнить: операторы сравнения требуют, чтобы типы операндов были совместимы. Попытка сравнить число со строкой с помощью > или < приведёт к ошибке выполнения, а сравнение через = просто вернёт Ложь. Это различие — частая причина «тихих» ошибок, когда код работает, но условие никогда не выполняется.
Как сравнивать примитивные значения: числа, строки, даты и булево
Числа сравниваются по значению без особенностей: 10 = 10 даст Истина. Сложности начинаются при сравнении чисел с разной точностью, полученных в результате расчётов. Из-за особенностей хранения дробных чисел результат вычислений может отличаться от ожидаемого на незначительную величину, и прямое сравнение на равенство даст Ложь. В таких случаях сравнивают разность с допустимой погрешностью или используют функцию округления перед сравнением.
Строки сравниваются посимвольно с учётом регистра и всех пробелов. Это значит, что "Иванов" и "иванов" — разные строки, а "Иванов " с пробелом в конце не равно "Иванов". Для регистронезависимого сравнения применяют функции ВРег() или НРег() к обоим операндам, а для очистки от пробелов — функцию СокрЛП(), которая удаляет неразрывные и обычные пробельные символы слева и справа.
Даты сравниваются как моменты времени с точностью до секунды. Две даты с одинаковым числом, но разным временем, не равны. Чтобы сравнить только календарные дни, приводят обе даты к началу дня функцией НачалоДня(), а для проверки попадания в период используют пару условий >= и <= с границами интервала.
Практический пример сравнения строк
Наименование1 = СокрЛП(Наименование1);
Наименование2 = СокрЛП(Наименование2);
Если ВРег(Наименование1) = ВРег(Наименование2) Тогда
// наименования совпадают без учёта регистра
КонецЕсли;
Как сравнивать ссылочные объекты: справочники и документы
Ссылочные объекты — ссылки на элементы справочников, документы, перечисления, планы видов характеристик — сравниваются по идентичности ссылки, а не по содержимому реквизитов. Два разных элемента справочника с полностью одинаковыми реквизитами всё равно не равны друг другу. Это принципиально: = для ссылок отвечает на вопрос «это один и тот же объект базы данных?», а не «у этих объектов одинаковые данные?».
Частая ситуация — сравнение ссылки с пустым значением. Для проверки на пустую ссылку используют метод Пустая() у ссылки или функцию ЗначениеЗаполнено(). Сравнение Ссылка = Неопределено не проверяет пустоту ссылки: Неопределено и пустая ссылка — разные вещи. Пустая ссылка — это вполне конкретное значение соответствующего типа, а Неопределено означает отсутствие значения как такового.
Для сравнения содержимого объектов по реквизитам прямой оператор не подходит. Нужно либо сравнивать конкретные реквизиты по отдельности, либо получать данные через запрос и сравнивать поля. Для глубокого сравнения структур данных иногда сериализуют объект в строку (например, через ЗначениеВСтрокуВнутр) и сравнивают строки, но этот способ требователен к ресурсам и применяется в ограниченных сценариях, например в механизмах версионирования.
Как проверить тип значения перед сравнением
Если переменная может содержать значения разных типов (например, реквизит составного типа или результат функции), перед сравнением стоит проверить тип. Для этого используют функцию ТипЗнч(), которая возвращает тип значения, и сравнивают результат с нужным типом через функцию Тип():
Если ТипЗнч(Значение) = Тип("СправочникСсылка.Контрагенты") Тогда
// можно безопасно работать как с контрагентом
КонецЕсли;
Такая проверка особенно важна в универсальных обработках, обменах данными и при работе с параметрами произвольного типа. Сравнение значений разных типов через = не вызывает ошибку, но всегда возвращает Ложь — и если разработчик ожидал другого, логика молча ломается. Операторы > и < для несовместимых типов, напротив, вызывают исключение, что хотя бы делает ошибку явной.
Отдельный случай — значение Неопределено. Оно возникает, когда переменной не присвоено значение, функция не вернула результат или реквизит не инициализирован. Сравнивать с ним можно только через = и <>; любые арифметические операции и сравнения порядка с Неопределено приведут к ошибке. Поэтому в начале процедур с необязательными параметрами принято явно задавать значения по умолчанию.
- 1Выведите оба сравниваемых значения через Сообщить() или посмотрите в отладчике
- 2Проверьте типы значений через ТипЗнч() — совпадают ли они
- 3Для строк проверьте наличие пробелов и регистр: сравните СокрЛП(ВРег(Значение)) с эталоном
- 4Для ссылок убедитесь, что сравниваются именно ссылки, а не строковые представления
- 5Для дат проверьте время и при необходимости приведите обе даты к НачалоДня()
- 6Повторите сравнение и убедитесь, что условие теперь даёт ожидаемый результат
Как сравнивать значения в запросах 1С
В языке запросов сравнение работает в условиях ГДЕ, в соединениях таблиц и в конструкции ВЫБОР КОГДА ... ТОГДА. Синтаксис операторов тот же, но поведение отличается в части NULL: любое сравнение с NULL возвращает не Истину или Ложь, а NULL, то есть «неизвестно». Записи с NULL в сравниваемых полях просто выпадают из результата, что часто выглядит как «запрос потерял данные».
Чтобы избежать потери записей, используют функцию ЕСТЬNULL(Поле, ЗначениеПоУмолчанию), которая подставляет значение вместо NULL, либо явную проверку Поле ЕСТЬ NULL / Поле ЕСТЬ НЕ NULL. Это особенно актуально при левых соединениях, где отсутствующие записи правой таблицы дают NULL во всех её полях.
Для сравнения строк в запросах доступен оператор ПОДОБНО с шаблоном (символ % — любая последовательность, _ — один символ), а для проверки вхождения в список значений — оператор В. Сравнение ссылок в запросах работает так же, как в коде: по идентичности ссылки. Передавать в параметр запроса нужно именно ссылку, а не её строковое представление или наименование.
Как сравнивать коллекции: массивы, структуры и таблицы значений
Коллекции в 1С нельзя сравнить оператором = по содержимому: сравнение двух массивов или структур проверяет не их элементы, а в большинстве случаев вообще не имеет смысла для прикладной задачи. Чтобы понять, совпадают ли две коллекции, нужно перебрать элементы и сравнить их попарно, предварительно проверив совпадение количества.
Для таблиц значений есть удобный приём: метод Найти() и НайтиСтроки() позволяют искать строки по условию равенства конкретных колонок, что фактически является сравнением. Если нужно сравнить две таблицы целиком, обычно выгружают их в запрос и выполняют полное соединение с проверкой расхождений — такой подход работает быстрее перебора и нагляднее показывает различия.
При сравнении структур полезен приём с сериализацией: структуру преобразуют в строку JSON встроенными средствами работы с JSON и сравнивают строки. Способ подходит для небольших структур без ссылочных значений и циклических ссылок. Для массивов простых значений иногда достаточно отсортировать оба массива и сравнить элементы по индексам.
Способы сравнения коллекций
Универсальный способ для массивов и структур. Прост в реализации, но требует аккуратной обработки разной длины коллекций
Оптимально для таблиц значений: быстро на больших объёмах, сразу показывает расхождения. Требует выгрузки таблиц в запрос
Подходит для небольших структур без ссылок. Ограничение: порядок ключей и форматирование должны совпадать
Как проверить, что сравнение написано правильно
Главный инструмент проверки — конфигуратор с отладчиком. Поставьте точку останова перед условием, посмотрите в табло значения обоих операндов и их типы, затем выполните сравнение по шагам. В большинстве случаев причина видна сразу: лишний пробел, другой тип, пустая ссылка вместо ожидаемого значения.
Второй уровень проверки — контрольные примеры. Подготовьте набор пар значений, для которых результат сравнения известен заранее: равные, отличающиеся регистром, отличающиеся пробелами, пустые. Прогоните через свою функцию сравнения все пары и сверьте результаты. Это особенно полезно для универсальных функций сравнения, которые переиспользуются в разных местах конфигурации.
Наконец, проверьте поведение на граничных случаях: пустые значения, Неопределено, NULL в запросах, максимально длинные строки, даты на границах периодов. Именно на границах сравнение ломается чаще всего, а в штатных данных ошибка может не проявляться месяцами.
Как проверить результат
Возвращает Истина
Возвращает Ложь — проверяйте типы, пробелы, регистр
Возвращает Ложь
Возвращает Истина — сравнение слишком «мягкое», например лишнее приведение типов
Пустая ссылка/строка/дата корректно распознаётся
Ошибка выполнения или неверный результат — нет проверки на Неопределено и пустоту
Все ожидаемые записи присутствуют
Часть записей потеряна — вероятен NULL, нужен ЕСТЬNULL
FAQ: частые вопросы о сравнении объектов в 1С
Почему условие «Ссылка = Справочники.Номенклатура.НайтиПоНаименованию(...)» не срабатывает?
Чаще всего метод НайтиПоНаименованию возвращает пустую ссылку, потому что элемент с таким наименованием не найден или наименование содержит лишние пробелы. Проверьте результат поиска на пустоту через Пустая() до сравнения и убедитесь, что наименование в базе совпадает с искомым с точностью до пробелов и регистра.
Чем отличается Неопределено от пустой ссылки?
Неопределено — это отсутствие значения как такового, оно не имеет прикладного типа. Пустая ссылка — конкретное значение определённого ссылочного типа, обозначающее «ни на что не указывает». Сравнение пустой ссылки с Неопределено даёт Ложь, поэтому для проверки пустых ссылок используйте метод Пустая() или функцию ЗначениеЗаполнено().
Как сравнить две строки без учёта регистра и пробелов?
Приведите обе строки функцией СокрЛП() для удаления краевых пробелов и функцией ВРег() или НРег() для выравнивания регистра, затем сравните результаты оператором =. Учтите, что пробелы внутри строки такой подход не убирает — если они тоже мешают, потребуется замена через СтрЗаменить().
Можно ли сравнивать объекты типа «объект справочника» (не ссылку)?
Оператор = для объектов сравнивает их по ссылке, то есть два объекта, загруженные из одной и той же записи базы, будут равны. Сравнить содержимое реквизитов одним оператором нельзя — нужно сравнивать реквизиты по отдельности или использовать сериализацию для комплексного сравнения.
Почему в запросе условие на равенство не находит записи, хотя значение совпадает?
Наиболее вероятные причины: поле содержит NULL (используйте ЕСТЬNULL), в параметр передано значение другого типа (например, строка вместо ссылки), либо строковое поле содержит неразрывные пробелы. Проверьте тип параметра и фактические данные в таблице через консоль запросов.
Как сравнить дробные числа, полученные в результате расчётов?
Избегайте прямого сравнения на равенство. Либо округлите оба значения до нужной точности функцией Окр() и сравните результаты, либо проверьте, что модуль разности меньше допустимой погрешности. Для денежных величин обычно достаточно округления до копеек перед сравнением.
Что важно запомнить
Примитивные значения в 1С сравниваются по содержимому, ссылочные — по идентичности ссылки. Перед сравнением приводите значения к одному типу, очищайте строки от пробелов и выравнивайте регистр. Пустые ссылки проверяйте через Пустая(), NULL в запросах — через ЕСТЬNULL, а дробные числа сравнивайте после округления. Отладчик и контрольные примеры — главные инструменты проверки корректности условий.