Конструкция Выбор-Когда (или Switch-Case в других языках программирования) — один из ключевых элементов управления потоком выполнения в 1С:Предприятие 8.3. Она позволяет заменить громоздкие цепочки условий Если-Тогда на компактный и читаемый код, особенно когда требуется проверить значение одной переменной на соответствие нескольким вариантам. Однако, несмотря на кажущуюся простоту, у этой конструкции есть нюансы, которые могут приводить к ошибкам или неоптимальной работе кода.
Многие разработчики 1С недооценивают гибкость Выбор-Когда, используя её только для примитивных проверок. Между тем, с её помощью можно организовывать сложную логику с вложенными условиями, работать с диапазонами значений, а также оптимизировать производительность за счёт сокращения количества проверок. В этой статье мы разберём синтаксис конструкции, покажем реальные примеры её применения в типовых задачах (от обработки документов до работы с справочниками), а также проанализируем типичные ошибки и способы их избежать.
Особое внимание уделим сравнению Выбор-Когда с альтернативными подходами — почему в некоторых случаях лучше использовать Если-Тогда-Иначе, а где без Выбор-Когда не обойтись. Также рассмотрим малоизвестные возможности, такие как использование конструкции с объектами 1С (например, СправочникСсылка) и работа с коллекциями.
Синтаксис конструкции Выбор-Когда: базовые правила
Конструкция Выбор-Когда в 1С 8.3 имеет следующий базовый синтаксис:
Выбор
Когда <Условие1> Тогда
// Действия 1
Когда <Условие2> Тогда
// Действия 2
...
Иначе
// Действия по умолчанию
КонецВыбора;
Ключевые особенности синтаксиса:
- 📌 Каждое условие Когда должно заканчиваться словом Тогда (в отличие от некоторых языков, где используется двоеточие или фигурные скобки).
- 📌 Блок Иначе не обязателен — если ни одно из условий не выполнено, выполнение кода просто продолжится после КонецВыбора.
- 📌 Внутри каждого блока Тогда может быть произвольное количество операторов, но они не требуют оборачивания в НачатьПопытку или другие конструкции.
- 📌 Условия проверяются последовательно, и выполнение прерывается после первого совпадения (в отличие от Если-Тогда, где можно использовать ИначеЕсли для продолжения проверок).
Важно понимать, что Выбор-Когда работает с одним выражением, которое сравнивается с разными вариантами. Например, если вам нужно проверить диапазон значений (например, Если Значение > 10 И Значение < 20), то Выбор-Когда для этого не подходит — здесь уместнее Если-Тогда.
Пример простейшего использования:
ДеньНедели = ДеньНедели(ТекущаяДата());
Выбор
Когда ДеньНедели = 1 Тогда
Сообщить("Понедельник - день тяжёлый");
Когда ДеньНедели = 5 Тогда
Сообщить("Пятница - почти выходной!");
Иначе
Сообщить("Обычный рабочий день");
КонецВыбора;
Если в блоке Когда нужно проверить несколько условий (например, Когда Значение = 10 Или Значение = 20), используйте логические операторы. Однако такой подход снижает читаемость — в этом случае лучше рассмотреть альтернативные конструкции.
Когда использовать Выбор-Когда, а когда Если-Тогда?
Многие разработчики 1С сталкиваются с дилеммой: что выбрать — Выбор-Когда или цепочку Если-Тогда-ИначеЕсли? Ответ зависит от конкретной задачи. Вот ключевые критерии:
| Критерий | Выбор-Когда | Если-Тогда-ИначеЕсли |
|---|---|---|
| Количество проверяемых условий | Много (3+) | Мало (1-2) |
| Тип проверки | Сравнение одного выражения с разными значениями | Разные условия (например, Если ТипДок = "Заказ" И Сумма > 1000) |
| Читаемость кода | Выше при большом количестве вариантов | Выше при сложных составных условиях |
| Производительность | Быстрее (проверки оптимизированы) | Медленнее при большом количестве условий |
| Вложенные условия | Не поддерживаются напрямую | Поддерживаются (можно использовать вложенные Если) |
Пример, где Выбор-Когда предпочтительнее:
Выбор
Когда ТипОперации = Тип("Документ.ПоступлениеТоваров") Тогда
// Логика для поступления
Когда ТипОперации = Тип("Документ.РеализацияТоваров") Тогда
// Логика для реализации
Когда ТипОперации = Тип("Документ.ВозвратОтПокупателя") Тогда
// Логика для возврата
КонецВыбора;
А здесь лучше Если-Тогда:
Если Номенклатура.ЭтоГруппа() И Номенклатура.ПометкаУдаления Тогда
Сообщить("Нельзя работать с помеченной группой!");
ИначеЕсли Номенклатура.Архивный Тогда
Сообщить("Номенклатура архивная!");
Иначе
// Основная логика
КонецЕсли;
Если вам нужно проверить одно и то же выражение на равенство разным значениям — используйте Выбор-Когда. Если условия разные и сложные — Если-Тогда будет уместнее.
Практические примеры использования Выбор-Когда
Рассмотрим реальные сценарии, где Выбор-Когда помогает сделать код лаконичнее и понятнее.
1. Обработка статусов документов
Типовая задача — выполнение разных действий в зависимости от статуса документа (например, "Согласован", "Отклонён", "Выполнен"):
Выбор
Когда СтатусДокумента = Перечисление.СтатусыДокументов.Согласован Тогда
РазрешитьПроводить();
ЗаписатьДокумент();
Когда СтатусДокумента = Перечисление.СтатусыДокументов.Отклонен Тогда
Сообщить("Документ отклонён! Причина: " + ПричинаОтклонения);
Когда СтатусДокумента = Перечисление.СтатусыДокументов.НаУтверждении Тогда
ОтправитьНаУтверждение(Руководитель);
КонецВыбора;
2. Работа с типами данных
Полезно при динамической обработке разных типов (например, в универсальных функциях):
Выбор
Когда ТипЗнч(Значение) = Тип("Строка") Тогда
Результат = СтрДлина(Значение);
Когда ТипЗнч(Значение) = Тип("Число") Тогда
Результат = Окр(Значение, 2);
Когда ТипЗнч(Значение) = Тип("Дата") Тогда
Результат = Формат(Значение, "ДФ=dd.MM.yyyy");
Иначе
Результат = Неопределено;
КонецВыбора;
3. Обработка кодов ошибок
При работе с API или внешними системами часто нужно реагировать на разные коды ответов:
КодОтвета = ПолучитьКодОтветаИзAPI();
Выбор
Когда КодОтвета = 200 Тогда
Сообщить("Успех!");
ОбработатьДанные(Ответ);
Когда КодОтвета = 401 Тогда
ВызватьИсключение("Не авторизован! Токен: " + ТокенДоступа);
Когда КодОтвета = 404 Тогда
Сообщить("Ресурс не найден");
Иначе
ЗаписатьВЛогОшибку(КодОтвета);
КонецВыбора;
4. Локализация сообщений
Если ваша конфигурация поддерживает несколько языков, Выбор-Когда удобен для выбора переводов:
Выбор
Когда ТекущийЯзык = "ru" Тогда
Сообщение = "Документ сохранён";
Когда ТекущийЯзык = "en" Тогда
Сообщение = "Document saved";
Когда ТекущийЯзык = "kk" Тогда
Сообщение = "Құжат сақталды";
КонецВыбора;
Убедитесь, что проверяется одно выражение|Проверьте, что условия не пересекаются|Добавьте блок Иначе для обработки неожиданных значений|Рассмотрите альтернативы, если условий больше 10-->
Типичные ошибки и как их избежать
Даже опытные разработчики 1С иногда допускают ошибки при работе с Выбор-Когда. Вот самые распространённые из них:
1. Отсутствие блока Иначе
Если не обработать вариант, когда ни одно из условий не выполнено, это может привести к логическим ошибкам. Например:
Выбор
Когда Цвет = "Красный" Тогда
Цена = Цена * 1.1;
Когда Цвет = "Синий" Тогда
Цена = Цена * 0.9;
// Нет блока Иначе!
КонецВыбора;
В этом случае, если Цвет будет "Зелёный", переменная Цена останется без изменений, что может быть неожиданным поведением.
2. Пересекающиеся условия
Если условия в блоках Когда пересекаются, выполнится только первое совпадение:
Выбор
Когда Возраст < 18 Тогда
Сообщить("Детский билет");
Когда Возраст < 25 Тогда // Это условие никогда не выполнится для возрастов 18-24!
Сообщить("Молодёжный билет");
КонецВыбора;
Чтобы избежать этого, располагайте условия от более частных к общим.
3. Сравнение ссылочных типов по значению
При работе со ссылками (например, СправочникСсылка.Номенклатура) сравнение по = может не сработать, если объекты разные, но имеют одинаковые реквизиты. Правильно:
Если Номенклатура1.Ссылка = Номенклатура2.Ссылка Тогда
// Правильное сравнение ссылок
КонецЕсли;
4. Использование сложных выражений в условиях
Если в блоке Когда указать выражение с побочными эффектами (например, вызов функции), оно будет выполняться даже если предыдущее условие уже сработало:
Выбор
Когда ПолучитьСтатусЗаказа(Заказ) = "Оплачен" Тогда // Функция вызовется всегда!
// ...
КонецВыбора;
Лучше заранее вычислить значение и сравнивать его:
Статус = ПолучитьСтатусЗаказа(Заказ);
Выбор
Когда Статус = "Оплачен" Тогда
// ...
КонецВыбора;
Что произойдёт, если не закрыть КонецВыбора?
В 1С 8.3 это приведёт к синтаксической ошибке на этапе компиляции модуля. Система выдаст сообщение "Ожидается 'КонецВыбора'" и укажет строку, где проблема. В отличие от некоторых языков (например, JavaScript), где отсутствие закрывающей скобки может привести к неявным ошибкам, в 1С это всегда ловится на этапе проверки кода.
Оптимизация производительности
При большом количестве условий в Выбор-Когда можно столкнуться с замедлением работы кода. Вот несколько способов оптимизации:
1. Располагайте условия по вероятности
Чаще выполняемые условия должны идти первыми. Например, если в 90% случаев статусом документа является "Согласован", поместите это условие первым:
Выбор
Когда Статус = "Согласован" Тогда // Частый случай
// ...
Когда Статус = "Отклонён" Тогда // Редкий случай
// ...
КонецВыбора;
2. Используйте хэш-таблицы для больших наборов данных
Если у вас десятки или сотни вариантов (например, обработка кодов регионов), Выбор-Когда станет неэффективным. Лучше использовать Соответствие:
КодыРегионов = Новый Соответствие;
КодыРегионов.Вставить(77, "Москва");
КодыРегионов.Вставить(78, "Санкт-Петербург");
// ...
Результат = КодыРегионов.Получить(КодРегиона, "Неизвестный регион");
3. Избегайте вычислений в условиях
Как упоминалось ранее, выражения в блоках Когда вычисляются всегда. Если вычисление ресурсоёмкое (например, запрос к базе), лучше вынести его за пределы конструкции.
4. Заменяйте на Если-Тогда при малом количестве условий
Для 2-3 вариантов Если-Тогда может быть быстрее из-за особенностей оптимизации платформы 1С.
Для 5+ условий Выбор-Когда обычно эффективнее цепочки Если-Тогда, но при 100+ вариантах рассмотрите альтернативные структуры данных (массивы, соответствия).
Работа с объектами 1С в Выбор-Когда
Конструкция Выбор-Когда может использоваться не только с примитивными типами (числа, строки), но и с объектами 1С. Рассмотрим несколько примеров.
1. Сравнение ссылок на справочники
Частая задача — выполнение разных действий в зависимости от выбранной номенклатуры или контрагента:
Выбор
Когда Номенклатура.Ссылка = Справочники.Номенклатура.Услуга1 Тогда
Цена = 1000;
Когда Номенклатура.Ссылка = Справочники.Номенклатура.Услуга2 Тогда
Цена = 2000;
Когда Номенклатура.ЭтоГруппа() Тогда
ВызватьИсключение("Нельзя выбирать группу номенклатуры!");
КонецВыбора;
2. Проверка типов документов
При обработке коллекции документов разных типов:
Для Каждого Док Из МассивДокументов Цикл
Выбор
Когда ТипЗнч(Док) = Тип("Документ.ПоступлениеТоваров") Тогда
ОбработатьПоступление(Док);
Когда ТипЗнч(Док) = Тип("Документ.РеализацияТоваров") Тогда
ОбработатьРеализацию(Док);
КонецВыбора;
КонецЦикла;
3. Работа с перечислениями
Перечисления в 1С идеально подходят для Выбор-Когда:
Выбор
Когда ВидОплаты = Перечисление.ВидыОплат.Наличные Тогда
Комиссия = 0;
Когда ВидОплаты = Перечисление.ВидыОплат.БанковскаяКарта Тогда
Комиссия = 1.5;
Когда ВидОплаты = Перечисление.ВидыОплат.ЭлектронныеДеньги Тогда
Комиссия = 2.0;
КонецВыбора;
Важно: при сравнении ссылок на объекты (например, справочников) всегда используйте оператор =, а не СокрЛП() или другие функции приведения типов. В противном случае сравнение может работать некорректно из-за особенностей хранения ссылок в 1С.
Альтернативные подходы: когда Выбор-Когда не подходит
Несмотря на гибкость, Выбор-Когда не всегда является лучшим решением. Рассмотрим альтернативы для разных сценариев.
1. Сложные составные условия
Если условия включают логические операторы (И, Или, НЕ), лучше использовать Если-Тогда:
Если (Сумма > 1000 И Валюта = "USD") Или Клиент.ВипСтатус Тогда
ПрименитьСкидку(10);
КонецЕсли;
2. Диапазоны значений
Для проверки попадания в диапазон удобнее Если:
Если Возраст >= 18 И Возраст < 25 Тогда
Сообщить("Молодёжная категория");
КонецЕсли;
3. Динамические условия
Если условия формируются динамически (например, из настроек пользователя), используйте массивы или соответствия:
УсловияСкидок = Новый Соответствие;
УсловияСкидок.Вставить("ВипКлиент", 10);
УсловияСкидок.Вставить("ОптовыйЗаказ", 5);
// ...
Скидка = УсловияСкидок.Получить(ТипКлиента, 0);
4. Вложенные проверки
Выбор-Когда не поддерживает вложенные конструкции. Для многоуровневой логики комбинируйте Выбор-Когда и Если:
Выбор
Когда ТипДокумента = "Заказ" Тогда
Если Сумма > 10000 Тогда
Сообщить("Крупный заказ!");
КонецЕсли;
Когда ТипДокумента = "Возврат" Тогда
// ...
КонецВыбора;
FAQ: Частые вопросы по Выбор-Когда в 1С
Можно ли использовать Выбор-Когда для проверки типа значения?
Да, это один из самых удобных сценариев. Пример:
Выбор
Когда ТипЗнч(Значение) = Тип("Число") Тогда
Сообщить("Это число: " + Значение);
Когда ТипЗнч(Значение) = Тип("Строка") Тогда
Сообщить("Это строка длиной " + СтрДлина(Значение));
КонецВыбора;
Такой подход часто используется в универсальных функциях обработки данных.
Как обработать ситуацию, когда ни одно условие не выполнено?
Используйте блок Иначе:
Выбор
Когда Условие1 Тогда
// ...
Когда Условие2 Тогда
// ...
Иначе
Сообщить("Неизвестное условие!"); // Выполнится, если ни одно из условий не сработало
КонецВыбора;
Если блок Иначе не указан, выполнение просто продолжится после КонецВыбора.
Можно ли использовать Выбор-Когда для обработки исключений?
Технически можно, но это не рекомендуется. Для обработки ошибок лучше использовать Попытка-Исключение:
Попытка
// Код, который может вызвать ошибку
Исключение
Выбор
Когда ТипЗнч(ОписаниеОшибки()) = Тип("ОшибкаПриВводеЗначения") Тогда
Сообщить("Некорректный ввод!");
Когда КодОшибки() = 1001 Тогда
Сообщить("Объект не найден");
КонецВыбора;
КонецПопытки;
Однако такой код сложно поддерживать — лучше разделять логику обработки ошибок и бизнес-логику.
Как оптимизировать Выбор-Когда с большим количеством условий (50+)?
Для большого числа условий (более 20-30) Выбор-Когда становится неэффективным. Альтернативы:
- 📊 Используйте Соответствие (ассоциативный массив) для хранения вариантов.
- 📊 Разбейте логику на несколько Выбор-Когда с группировкой условий.
- 📊 Вынесите условия в отдельную таблицу базы данных и используйте запрос для получения результата.
Пример с Соответствием:
ДействияПоКодам = Новый Соответствие;
ДействияПоКодам.Вставить(100, "ОбработатьЗаказ");
ДействияПоКодам.Вставить(200, "ОтменитьЗаказ");
// ...
Действие = ДействияПоКодам.Получить(КодДействия, "НеизвестноеДействие");
Почему моя конструкция Выбор-Когда не работает с объектами?
Частая ошибка — сравнение объектов по значению вместо сравнения ссылок. Например:
// Некорректно (сравниваются значения, а не ссылки)
Когда Номенклатура1 = Номенклатура2 Тогда
// Корректно (сравниваются ссылки)
Когда Номенклатура1.Ссылка = Номенклатура2.Ссылка Тогда
Также убедитесь, что объекты не являются Неопределено — это может приводить к неожиданным результатам.
Если вам нужно отладить работу Выбор-Когда, добавьте временное сообщение в каждый блок Когда и Иначе, чтобы увидеть, какое условие срабатывает. Например: Сообщить("Сработало условие 1: " + Условие1);
⚠️ Внимание: В некоторых версиях платформы 1С:Предприятие (особенно до 8.3.10) существовали баги с оптимизацией конструкции Выбор-Когда при большом количестве условий. Если вы работаете со старыми конфигурациями, тестируйте производительность на реальных данных.