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