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