К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как работают операторы встроенного языка 1С

Как работают операторы встроенного языка 1С: арифметические, логические, сравнения и присваивание. Примеры кода, приоритеты, типичные ошибки и проверка результата.

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

Материал рассчитан на тех, кто начинает программировать в 1С или переходит с другого языка. Разберём основные группы операторов, их приоритет, особенности работы с типами данных и типичные ловушки, которые встречаются даже у опытных разработчиков.

Все примеры приведены на встроенном языке 1С (русский синтаксис) и работают как в толстом, так и в тонком клиенте, если не оговорено иное.

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

В 1С один и тот же символ «=» используется и для присваивания, и для сравнения. Если знак стоит в начале выражения как отдельная инструкция — это присваивание. Если он находится внутри условия или выражения — это сравнение, возвращающее булево значение.

Цена = 100;              // присваивание

Если Цена = 100 Тогда // сравнение

Сообщить("Цена равна ста");

КонецЕсли;

Такое совмещение удобно для новичков, но создаёт риск: случайно написанное присваивание вместо сравнения не вызовет синтаксической ошибки, если оно синтаксически допустимо в данном контексте. Поэтому при чтении чужого кода всегда проверяйте, где именно стоит знак равенства.

Присваивание в 1С — это копирование значения, а не ссылки, для примитивных типов (число, строка, дата, булево). Для объектов базы данных (ссылки на справочники и документы) присваивается сама ссылка, а не копия объекта — изменение реквизитов через одну переменную отразится на объекте в целом.

Арифметические операторы и работа с типами

Доступны стандартные операции: сложение (+), вычитание (−), умножение (*), деление (/) и остаток от деления (%). Унарный минус меняет знак числа. Оператор + работает и со строками — выполняет конкатенацию.

Сумма = 10 + 5;        // 15

Текст = "Итого: " + Сумма; // "Итого: 15"

Остаток = 10 % 3; // 1

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

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

Операторы сравнения и логические операции

Сравнение выполняется операторами =, <> (не равно), >, <, >=, <=. Результат — всегда булево значение Истина или Ложь. Сравнивать можно значения одного примитивного типа; сравнение числа со строкой вызовет ошибку.

Логические операторы: И, Или, Не. Они работают с булевыми значениями и поддерживают «ленивое» вычисление: если первый операнд оператора И равен Ложь, второй не вычисляется. Это важно, когда во втором операнде стоит вызов функции — она не будет выполнена.

Если Документ <> Неопределено И Документ.Проведен Тогда

// Документ существует и проведён

КонецЕсли;

Для проверки «пустоты» значения используйте специальные значения: Неопределено (отсутствие значения), NULL (результат запроса), пустые ссылки (Справочники.Номенклатура.ПустаяСсылка()). Сравнение с ними выполняется обычным оператором равенства, но смешивать их нельзя: NULL не равен Неопределено.

Условный оператор Если и тернарный выбор

Условный оператор имеет вид: Если ... Тогда ... ИначеЕсли ... Тогда ... Иначе ... КонецЕсли. Ветвей ИначеЕсли может быть сколько угодно, ветка Иначе необязательна. Каждое условие должно вычисляться в булево значение — передать туда число или строку нельзя, будет ошибка выполнения.

Для коротких выборов значения удобен оператор ?(Условие, ЗначениеЕслиИстина, ЗначениеЕслиЛожь) — аналог тернарного оператора в других языках:

Статус = ?(Сумма > 0, "Оплачено", "Не оплачено");

Частая ошибка — глубокая вложенность Если внутри Если. Код с четырьмя-пятью уровнями вложенности тяжело читать и отлаживать. Заменяйте цепочки на ранние выходы из процедуры (Возврат) или выносите проверки в отдельные функции, возвращающие булево.

Операторы циклов: Для, Для Каждого, Пока

Цикл Для используется, когда известно число итераций: Для Сч = 1 По 10 Цикл ... КонецЦикла. Переменная счётчика создаётся автоматически, шаг всегда равен 1 — отрицательный шаг не поддерживается, для обратного обхода вычисляйте индекс вручную.

Цикл Для Каждого ... Из ... Цикл перебирает элементы коллекций: массивов, таблиц значений, выборок из запроса, списков значений. Это основной способ обхода данных в 1С:

Для Каждого СтрокаТовара Из Товары Цикл

СтрокаТовара.Сумма = СтрокаТовара.Цена * СтрокаТовара.Количество;

КонецЦикла;

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

Операторы Прервать и Продолжить управляют циклом: Прервать полностью выходит из цикла, Продолжить переходит к следующей итерации. Они действуют только на ближайший вложенный цикл — выйти сразу из двух уровней вложенности одним Прервать нельзя.

Типичные ошибки
01
Модификация коллекции внутри цикла Для Каждого по самой этой коллекции — удаление строк таблицы во время обхода приводит к пропуску элементов; сначала соберите строки для удаления в отдельный массив
02
Бесконечный цикл Пока из-за забытого изменения переменной условия — сеанс зависает до таймаута
03
Запрос к базе внутри цикла вместо одного запроса по всей таблице — резкое падение производительности при большом объёме данных
04
Сравнение числа со строкой без явного приведения типов — ошибка выполнения в боевой базе

Оператор Попытка и обработка ошибок

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

Попытка

Результат = Сумма / Количество;

Исключение

Инфо = ИнформацияОбОшибке();

ЗаписьЖурналаРегистрации("Расчёт", , , , Инфо.Описание);

Результат = 0;

КонецПопытки;

Оператор ВызватьИсключение позволяет создать ошибку самостоятельно — с текстом сообщения или повторно пробросить перехваченную. Это полезно для проверки входных параметров процедур: если аргумент недопустим, лучше сразу вызвать исключение с понятным текстом, чем получить неочевидную ошибку глубже в коде.

Не используйте Попытка как способ «спрятать» ошибки: пустой блок Исключение без журналирования делает диагностику проблем почти невозможной. Минимум — записывайте ошибку в журнал регистрации.

Приоритет операторов и проверка результата

Порядок вычисления: сначала унарные операторы и Не, затем умножение/деление/остаток, затем сложение/вычитание, затем сравнения, затем И, в конце — Или. Сомневаетесь в приоритете — ставьте скобки: они не влияют на производительность, но делают намерение явным.

ПриоритетОператорыПример
1 (высший)Не, унарный минусНе Флаг, -Сумма
2, /, %Цена Количество
3+, −Сумма + НДС
4=, <>, >, <, >=, <=Итог > 0
5ИУсл1 И Усл2
6 (низший)ИлиУсл1 Или Усл2

Выражение «А И Б Или В» вычисляется как «(А И Б) Или В», а не «А И (Б Или В)» — это частый источник логических ошибок в сложных условиях.

Контрольные точки

Как проверить результат

Код компилируется
Норма

Конфигуратор не сообщает об ошибках синтаксиса при проверке модуля

Тревожный признак

Сообщения о незакрытых операторных скобках или неизвестных именах

Логика условий
Норма

При тесте на граничных значениях (0, пустая ссылка, Неопределено) результат совпадает с ожидаемым

Тревожный признак

Ветка Иначе срабатывает там, где должна сработать основная

Циклы
Норма

Цикл завершается за предсказуемое время, все элементы обработаны

Тревожный признак

Зависание сеанса или пропущенные строки коллекции

Обработка ошибок
Норма

Ошибка попадает в журнал регистрации с понятным текстом

Тревожный признак

Ошибка «проглатывается», в журнале пусто

Практический порядок освоения

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

Порядок действий
  1. 1
    Создайте внешнюю обработку и в модуле формы напишите простое присваивание и вывод через Сообщить()
  2. 2
    Добавьте условие Если с проверкой значения и веткой Иначе
  3. 3
    Организуйте цикл Для Каждого по таблице значений с накоплением суммы
  4. 4
    Оберните потенциально опасное вычисление в Попытка...Исключение с записью в журнал регистрации
  5. 5
    Проверьте поведение на граничных значениях: 0, пустая строка, Неопределено
Итог

Что важно запомнить

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

Частые вопросы

Чем отличается Неопределено от NULL в 1С?

Неопределено — значение встроенного языка, означающее отсутствие данных (например, незаполненный параметр). NULL появляется только в результатах запросов при левом соединении или отсутствующих полях. Они не равны друг другу, и NULL нужно обрабатывать функцией ЕСТЬNULL() прямо в запросе.

Можно ли использовать && и || вместо И и Или?

Нет, встроенный язык 1С не поддерживает такие сокращения. Используйте ключевые слова И, Или, Не — в русском или английском синтаксисе (And, Or, Not), но не символы из C-подобных языков.

Как выйти сразу из двух вложенных циклов?

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

Почему сложение числа и строки вызывает ошибку?

Встроенный язык не выполняет неявное преобразование между числом и строкой в арифметических операциях. Приведите значение явно: Строка(ЧислоЗначение) для конкатенации или Число(СтрокаЗначение) для вычисления, предварительно убедившись, что строка содержит корректное число.

Работает ли оператор ?() на сервере и на клиенте?

Да, тернарный оператор ?(Условие, Значение1, Значение2) доступен в любом контексте выполнения — тонкий клиент, веб-клиент, сервер. Ограничений по директивам компиляции у него нет.

Какой цикл быстрее: Для или Для Каждого?

Для обхода коллекций предпочтителен Для Каждого — он читаемее и не требует обращения по индексу. Разница в скорости на типовых объёмах данных несущественна; реальные потери производительности обычно связаны с запросами внутри цикла, а не с выбором конструкции обхода.