Конструкция ВЫБОР КОГДА ИНАЧЕ (аналог switch-case в других языках) — один из ключевых элементов встроенного языка 1С:Предприятие 8. Она позволяет писать компактный и читаемый код для ветвления логики по нескольким условиям, избегая громоздких вложенных ЕСЛИ. Однако даже опытные разработчики 1С иногда сталкиваются с нюансами её работы: от синтаксических ошибок до проблем с производительностью.

В этой статье мы разберём не только базовый синтаксис конструкции, но и малоизвестные особенности её поведения в разных контекстах — от серверных процедур до клиентских обработчиков. Вы узнаете, как правильно оформлять ВЫБОР для работы с перечислениями, датами и динамическими условиями, а также когда лучше заменить её на альтернативные подходы. Особое внимание уделим типичным ошибкам, которые приводят к падению производительности или некорректной работе кода.

1. Синтаксис конструкции ВЫБОР КОГДА ИНАЧЕ

Базовая структура конструкции выглядит так:

ВЫБОР

КОГДА <Условие1> ТОГДА

// Действия 1

КОГДА <Условие2> ТОГДА

// Действия 2

...

ИНАЧЕ

// Действия по умолчанию

КОНЕЦВЫБОРА;

Ключевые особенности синтаксиса:

  • 🔹 Ключевое слово ТОГДА обязательно — его пропуск приведёт к синтаксической ошибке. Это частая опечатка у новичков.
  • 🔹 Блок ИНАЧЕ не обязателен, но его отсутствие требует явной обработки всех возможных случаев.
  • 🔹 Условия проверяются последовательно — как только выполняется одно из них, остальные ветки игнорируются (в отличие от ЕСЛИ, где можно использовать ИНАЧЕЕСЛИ).
  • 🔹 Внутри блоков можно использовать любые операторы, включая вложенные ВЫБОР или ЕСЛИ.

Пример с перечислением:

ВЫБОР

КОГДА ТипДокумента = Перечисление.ТипыДокументов.ЗаказПокупателя ТОГДА

Сообщить("Обработка заказа");

КОГДА ТипДокумента = Перечисление.ТипыДокументов.Реализация ТОГДА

Сообщить("Оформление реализации");

ИНАЧЕ

Сообщить("Неизвестный тип документа!");

КОНЕЦВЫБОРА;

📊 Как часто вы используете ВЫБОР КОГДА в коде 1С?
Постоянно
Иногда
Редеко
Предпочитаю ЕСЛИ
Не знаю, что это

2. Когда использовать ВЫБОР вместо ЕСЛИ

Конструкция ВЫБОР не является универсальной заменой ЕСЛИ — у неё есть специфические случаи применения:

Критерий ВЫБОР КОГДА ЕСЛИ
Количество условий 3 и более 1–2
Тип условий Проверка на равенство (=) или перечисления Любые логические выражения (>, <, И, ИЛИ)
Читаемость Выше при множестве однотипных проверок Лучше для сложной логики с И/ИЛИ
Производительность Быстрее при большом количестве веток (оптимизировано платформой) Может быть медленнее из-за последовательной проверки

Пример, где ВЫБОР предпочтительнее:

ВЫБОР

КОГДА СтатусЗаказа = Перечисление.СтатусыЗаказов.Новый ТОГДА

Цвет = Новый Цвет(0, 255, 0); // Зелёный

КОГДА СтатусЗаказа = Перечисление.СтатусыЗаказов.ВРаботе ТОГДА

Цвет = Новый Цвет(255, 255, 0); // Жёлтый

КОГДА СтатусЗаказа = Перечисление.СтатусыЗаказов.Выполнен ТОГДА

Цвет = Новый Цвет(0, 0, 255); // Синий

КОГДА СтатусЗаказа = Перечисление.СтатусыЗаказов.Отменён ТОГДА

Цвет = Новый Цвет(255, 0, 0); // Красный

КОНЕЦВЫБОРА;

💡

Если условия в ВЫБОР взаимно исключают друг друга (например, проверка значений перечисления), блок ИНАЧЕ можно опустить — это ускорит выполнение кода на 5–10% за счёт отсутствия лишней проверки.

3. Работа с динамическими условиями и сложными выражениями

В отличие от switch-case в классических языках программирования, конструкция ВЫБОР КОГДА в 1С поддерживает произвольные логические выражения в условиях, а не только проверку на равенство. Это открывает широкие возможности, но требует осторожности.

Примеры динамических условий:

  • 📅 Проверка диапазонов дат:
    КОГДА ТекущаяДата() >= НачалоКвартала И ТекущаяДата() < КонецКвартала ТОГДА
  • 🔢 Сравнение с результатом функции:
    КОГДА СтрДлина(Клиент.Наименование) > 50 ТОГДА
  • 📊 Проверка принадлежности к группе:
    КОГДА Товар.Группа.ЭтоГруппа(Справочники.Номенклатура.Мебель) ТОГДА

Однако есть подводные камни:

⚠️ Внимание: Если условия в ВЫБОР содержат вызов функций или методов с побочными эффектами (например, запись в базу), они будут выполняться даже для невыбранных веток. Например:
КОГДА ПолучитьОстаток(Товар) > 0 ТОГДА  // Функция выполнится всегда!

Чтобы избежать этого, предварительно сохраняйте результаты в переменные.

Как оптимизировать сложные условия в ВЫБОР?

Если условие требует вычислений (например, обращение к базе), вынесите его в отдельную переменную ДО конструкции ВЫБОР:

Остаток = ПолучитьОстаток(Товар); // Вычисляем один раз

ВЫБОР

КОГДА Остаток > 0 ТОГДА

// ...

КОНЕЦВЫБОРА;

Это ускорит код и избежит повторных обращений.

4. Типичные ошибки и как их избежать

Даже опытные разработчики 1С допускают ошибки при работе с ВЫБОР КОГДА. Вот наиболее распространённые:

  1. Пропуск ТОГДА:
    КОГДА Условие  // Ошибка! Нет "ТОГДА"
    

    Сообщить("...");

    выдаст синтаксическую ошибку: "Ожидалось 'ТОГДА'".
  2. Использование оператора присваивания (=) вместо сравнения (=):
    КОГДА Переменная = 10 ТОГДА  // Ошибка! Это присваивание, а не сравнение

    Правильно: КОГДА Переменная = 10 ТОГДА (в 1С знак = используется и для сравнения, и для присваивания, но в условиях ВЫБОР работает только как сравнение).

  3. Забытый КОНЕЦВЫБОРА:
    ВЫБОР
    

    КОГДА Условие1 ТОГДА

    // ...

    // Ошибка! Нет КОНЕЦВЫБОРА

    Приведёт к ошибке компиляции: "Ожидалось 'КОНЕЦВЫБОРА'".

  4. Пустые ветки КОГДА:
    КОГДА Условие1 ТОГДА
    

    // Пусто (ошибка!)

    Ветка должна содержать хотя бы один оператор (можно использовать ; или Продолжить).

Особое внимание заслуживает ошибка с неполным покрытием условий:

ВЫБОР

КОГДА Статус = 1 ТОГДА

Сообщить("Статус 1");

КОГДА Статус = 2 ТОГДА

Сообщить("Статус 2");

// Нет блока ИНАЧЕ и не все статусы обработаны!

КОНЕЦВЫБОРА;

⚠️ Внимание: Если переменная Статус примет значение 3 или Неопределён, ни одна ветка не сработает, что может привести к логическим ошибкам. Всегда проверяйте покрытие условий или добавляйте блок ИНАЧЕ с обработкой исключений.

5. Оптимизация производительности

Конструкция ВЫБОР КОГДА в 1С оптимизирована платформой, но есть способы сделать её ещё эффективнее:

  • Располагайте частые условия первыми — платформа проверяет условия последовательно, и ранний выход ускоряет выполнение.
  • Избегайте тяжелых вычислений в условиях — выносите их в переменные (см. раздел 3).
  • Используйте перечисления вместо "магических чисел" — это ускоряет сравнение:
    КОГДА Статус = Перечисление.Статусы.Активен ТОГДА  // Быстрее, чем сравнение с числом
  • Заменяйте вложенные ВЫБОР на таблицы соответствий — для больших объёмов данных:

Пример оптимизации с таблицей соответствий:

СоответствиеСтатусов = Новый Соответствие;

СоответствиеСтатусов.Вставить(Перечисление.Статусы.Новый, "Обработка");

СоответствиеСтатусов.Вставить(Перечисление.Статусы.Выполнен, "Готово");

// Быстрая проверка без ВЫБОР:

Если СоответствиеСтатусов.Содержит(ТекущийСтатус) ТОГДА

Сообщить(СоответствиеСтатусов[ТекущийСтатус]);

КонецЕсли;

Для критичных по производительности участков (например, в циклах по 10 000+ строк) замена ВЫБОР на Соответствие может дать прирост скорости в 2–5 раз.

💡

Если в ВЫБОР более 10 веток, рассмотрите возможность использования Соответствие или массива для хранения действий. Это особенно актуально для серверных процедур с высокой нагрузкой.

6. Альтернативные подходы: когда ВЫБОР не подходит

Несмотря на гибкость, ВЫБОР КОГДА не всегда оптимален. Рассмотрим альтернативы:

Задача Лучший инструмент Пример
Сложные логические условия (И/ИЛИ) ЕСЛИ ... ИНАЧЕЕСЛИ
ЕСЛИ (Условие1 И Условие2)

ИЛИ Условие3 ТОГДА

Динамическое формирование условий Массив функций + Выполнить()
Действия = Новый Массив();

Действия.Добавить(Функция() Возврат 1; КонецФункции);

Обработка диапазонов значений ЕСЛИ с проверкой границ
ЕСЛИ Значение >= 0

И Значение <= 100 ТОГДА

Множественный выбор (флаги) Побитовые операции
ЕСЛИ (Флаги И Флаг1) <> 0 ТОГДА

Пример, где ЕСЛИ удобнее:

ЕСЛИ (Товар.Категория = Категория.Электроника И Товар.Цена > 1000)

ИЛИ (Товар.Поставщик.Надёжный И Товар.НаСкладе < 10) ТОГДА

Приоритет = Высокий;

ИНАЧЕ

Приоритет = Низкий;

КОНЕЦЕСЛИ;

Для динамического выбора действий (например, в зависимости от настроек пользователя) удобнее использовать массив функций:

Действия = Новый Массив();

Действия.Добавить(Функция() Сообщить("Действие 1"); КонецФункции);

Действия.Добавить(Функция() Сообщить("Действие 2"); КонецФункции);

// Вызов по индексу:

Действия[Индекс].Выполнить();

7. Практические примеры для типовых задач 1С

Рассмотрим реальные сценарии использования ВЫБОР КОГДА в типовых конфигурациях:

Проверьте, что условия взаимно исключают друг друга

Вынесите тяжелые вычисления в переменные

Используйте перечисления вместо чисел/строк

Добавьте блок ИНАЧЕ для обработки исключений

Протестируйте все ветки кода-->

Пример 1: Обработка статусов документа

ВЫБОР

КОГДА Документ.Статус = Перечисление.СтатусыДокументов.Проведён ТОГДА

РазрешитьРедактирование = Ложь;

ЦветФона = Новый Цвет(220, 255, 220); // Светло-зелёный

КОГДА Документ.Статус = Перечисление.СтатусыДокументов.Отменён ТОГДА

РазрешитьРедактирование = Истина;

ЦветФона = Новый Цвет(255, 220, 220); // Светло-красный

КОГДА Документ.Статус = Перечисление.СтатусыДокументов.Черновик ТОГДА

РазрешитьРедактирование = Истина;

ЦветФона = Новый Цвет(255, 255, 220); // Светло-жёлтый

ИНАЧЕ

ВызватьИсключение "Неизвестный статус документа: " + Документ.Статус;

КОНЕЦВЫБОРА;

Пример 2: Форматирование вывода в отчёт

ВЫБОР

КОГДА ТипЗначения(Значение) = Тип("Число") ТОГДА

Результат = Формат(Значение, "ЧДЦ=2; ЧГ= ");

КОГДА ТипЗначения(Значение) = Тип("Дата") ТОГДА

Результат = Формат(Значение, "ДФ=dd.MM.yyyy");

КОГДА ТипЗначения(Значение) = Тип("Строка") ТОГДА

Результат = СокрЛП(Значение);

ИНАЧЕ

Результат = "?" + ТипЗначения(Значение);

КОНЕЦВЫБОРА;

Пример 3: Маршрутизация обработчиков событий

ВЫБОР

КОГДА Событие = "НачалоРаботыСистемы" ТОГДА

ЗапуститьФоновуюЗадачу("ОбновлениеКурсовВалют");

КОГДА Событие = "ОшибкаОбмена" ТОГДА

ОтправитьУведомлениеАдминистратору(ОписаниеОшибки);

КОГДА СтрНачинаетсяС(Событие, "Документ.") ТОГДА

ОбработатьСобытиеДокумента(Событие);

ИНАЧЕ

ЗаписатьВЛог("Необработанное событие: " + Событие, УровеньЛога.Предупреждение);

КОНЕЦВЫБОРА;

⚠️ Внимание: В клиент-серверных решениях избегайте размещения конструкции ВЫБОР с обращением к базе данных в цикле на клиенте. Например:
Для Каждого Строка Из ТабличнаяЧасть Цикл

ВЫБОР // Плохо! Запросы к серверу в каждом витке цикла

КОГДА Строка.Номенклатура.ЭтоГруппа() ТОГДА

// ...

КОНЕЦВЫБОРА;

КонецЦикла;

Лучше загрузите все необходимые данные одним запросом до цикла.

FAQ: Частые вопросы по ВЫБОР КОГДА ИНАЧЕ

Можно ли использовать ВЫБОР без ИНАЧЕ?

Да, блок ИНАЧЕ не обязателен. Однако если ни одно из условий КОГДА не выполнится, управление передастся оператору, следующему за КОНЕЦВЫБОРА. Это может привести к логическим ошибкам, если вы ожидаете обработку всех случаев. Например:

ВЫБОР

КОГДА А = 1 ТОГДА Сообщить("1");

КОГДА А = 2 ТОГДА Сообщить("2");

КОНЕЦВЫБОРА;

Сообщить("Готово"); // Выполнится, если А = 3

Как обработать диапазон значений в ВЫБОР?

Платформа 1С не поддерживает синтаксис вида КОГДА Значение В (1, 10) (в отличие от SQL). Используйте явные сравнения:

КОГДА Значение >= 1 И Значение <= 10 ТОГДА

Для частых проверок диапазонов рассмотрите возможность использования Соответствие или массива с предварительно рассчитанными границами.

Почему ВЫБОР работает медленнее, чем ЕСЛИ, в моём коде?

Это возможно в двух случаях:

  1. Вы используете сложные условия с вызовами функций внутри КОГДА (см. раздел 3).
  2. У вас много веток (20+), и платформа тратит время на последовательную проверку. В этом случае замените ВЫБОР на Соответствие или хэш-таблицу.

Для точной диагностики используйте профилировщик 1С (меню Сервис → Профилировщик).

Можно ли вложить один ВЫБОР в другой?

Да, вложенные конструкции ВЫБОР разрешены, но их глубина не должна превышать 10 уровней (ограничение платформы). Пример:

ВЫБОР

КОГДА ТипДокумента = "Заказ" ТОГДА

ВЫБОР

КОГДА Статус = "Новый" ТОГДА

// ...

КОНЕЦВЫБОРА;

КОГДА ТипДокумента = "Реализация" ТОГДА

// ...

КОНЕЦВЫБОРА;

Однако злоупотребление вложенностью ухудшает читаемость. Для сложной логики лучше вынести внутренние проверки в отдельные функции.

Как отлаживать код с ВЫБОР КОГДА?

Используйте следующие приёмы:

  • 🐞 Точки останова на каждой ветке КОГДА (в отладчике 1С).
  • 📝 Логирование с указанием выполненной ветки:
    КОГДА Условие1 ТОГДА
    

    ЗаписатьЛог("Выполнена ветка 1");

  • 🔍 Проверка покрытия — добавьте в блок ИНАЧЕ вывод необработанного значения:
    ИНАЧЕ
    

    Сообщить("Необработанное значение: " + Значение);