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