Как проверить, является ли значение ссылкой на любое перечисление в 1С

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

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

Способ 1. Использование системного метода ТипВсеСсылки()

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


Если Перечисления.ТипВсеСсылки().СодержитТип(ТипЗнч(МояСсылка)) Тогда
    // Это значение является одним из перечислений, заданных в конфигурации
    Сообщить("Тип значения — Перечисление");
КонецЕсли;

Разберем по шагам, что происходит в этой строке кода. Функция ТипЗнч(МояСсылка) возвращает объект типа Тип. Метод Перечисления.ТипВсеСсылки() возвращает системный объект ОписаниеТипов, который содержит в себе массив всех типов перечислений, существующих в текущей конфигурации. Затем с помощью метода СодержитТип() мы проверяем, входит ли наш тип в этот список.

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

Способ 2. Проверка через объект метаданных (Оптимальный вариант)

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


// Получаем объект метаданных по типу значения
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(МояСсылка));

// Проверяем, содержится ли этот объект в коллекции перечислений
Если ОбъектМетаданных <> Неопределено И Метаданные.Перечисления.Содержит(ОбъектМетаданных) Тогда
    // Значение является ссылкой на перечисление
    Сообщить("Это перечисление: " + ОбъектМетаданных.Имя);
КонецЕсли;

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

Способ 3. Проверка по полному имени метаданных

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


ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(МояСсылка));
Если ОбъектМетаданных <> Неопределено Тогда
    Если СтрНачинаетсяС(ОбъектМетаданных.ПолноеИмя(), "Перечисление.") Тогда
        // Подтверждено, что это перечисление
    КонецЕсли;
КонецЕсли;

Этот метод удобен тем, что он легко расширяется. Например, если нам нужно проверить, является ли объект справочником или документом, мы просто меняем строку префикса на "Справочник." или "Документ." соответственно. Функция СтрНачинаетсяС() появилась в платформе 8.3.10, для более старых версий следует использовать Лев(ОбъектМетаданных.ПолноеИмя(), 13) = "Перечисление.".

Способ 4. Кэширование для высоконагруженных участков

Если в вашем коде по каким-то архитектурным причинам все же необходимо использовать ОписаниеТипов, мы рекомендуем прибегнуть к механизму кэширования. Это позволит избежать повторного создания тяжелого объекта при каждом обращении.

Проанализируем пример использования в модуле с повторным использованием значений:


// В общем модуле с установленным свойством "Повторное использование: На время вызова" или "На время сеанса"
Функция ПолучитьОписаниеВсехПеречислений() Экспорт
    Возврат Перечисления.ТипВсеСсылки();
КонецФункции

// Использование в коде:
Если ПолучитьОписаниеВсехПеречислений().СодержитТип(ТипЗнч(МояСсылка)) Тогда
    // Обработка
КонецЕсли;

Благодаря кэшированию, платформа вычислит список типов только один раз, а при последующих вызовах будет мгновенно возвращать готовый результат из памяти.

Особенности проверки в запросах

Важно помнить, что в языке запросов 1С универсальной проверки «на любое перечисление» не существует. В запросе мы всегда должны работать с конкретными типами данных. Если нам нужно проверить поле на принадлежность к определенному перечислению, мы используем оператор ССЫЛКА:


ВЫБРАТЬ
    Продажи.Ссылка
ИЗ
    Документ.РеализацияТоваровУслуг КАК Продажи
ГДЕ
    Продажи.Статус ССЫЛКА Перечисление.СтатусыРеализаций

Если в поле может храниться составной тип, включающий несколько разных перечислений, вам придется перечислять их все через условие ИЛИ. Универсальная проверка ССЫЛКА Перечисления (во множественном числе) синтаксически невозможна.

Подведение итогов

Мы рассмотрели несколько способов решения задачи. Подведем итог:

  1. Для быстрой разовой проверки в несложных конфигурациях допустимо использовать Перечисления.ТипВсеСсылки().СодержитТип().
  2. Для профессиональной разработки и обеспечения высокой производительности следует использовать Метаданные.НайтиПоТипу().
  3. При работе с универсальными алгоритмами анализа строк удобно проверять ОбъектМетаданных.ПолноеИмя().
  4. В запросах всегда требуется указание конкретного типа перечисления.

Выбор метода зависит от контекста вашей задачи, но понимание того, как платформа работает с типами «под капотом», позволит вам писать более качественный и быстрый код.

← На главную