Разработка и Конфигурация · 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С:
Для Каждого СтрокаТовара Из Товары Цикл
СтрокаТовара.Сумма = СтрокаТовара.Цена * СтрокаТовара.Количество;
КонецЦикла;
Цикл Пока Условие Цикл выполняется, пока условие истинно. Здесь критично гарантировать выход: если условие никогда не станет ложным, сеанс зависнет, и на сервере такой код может быть прерван только по таймауту. Всегда изменяйте внутри цикла переменную, участвующую в условии.
Операторы Прервать и Продолжить управляют циклом: Прервать полностью выходит из цикла, Продолжить переходит к следующей итерации. Они действуют только на ближайший вложенный цикл — выйти сразу из двух уровней вложенности одним Прервать нельзя.
Оператор Попытка и обработка ошибок
Конструкция Попытка ... Исключение ... КонецПопытки перехватывает ошибки выполнения. В блоке Исключение доступна функция ОписаниеОшибки() и объект ИнформацияОбОшибке(), из которого можно получить подробный текст и стек вызовов.
Попытка
Результат = Сумма / Количество;
Исключение
Инфо = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("Расчёт", , , , Инфо.Описание);
Результат = 0;
КонецПопытки;
Оператор ВызватьИсключение позволяет создать ошибку самостоятельно — с текстом сообщения или повторно пробросить перехваченную. Это полезно для проверки входных параметров процедур: если аргумент недопустим, лучше сразу вызвать исключение с понятным текстом, чем получить неочевидную ошибку глубже в коде.
Не используйте Попытка как способ «спрятать» ошибки: пустой блок Исключение без журналирования делает диагностику проблем почти невозможной. Минимум — записывайте ошибку в журнал регистрации.
Приоритет операторов и проверка результата
Порядок вычисления: сначала унарные операторы и Не, затем умножение/деление/остаток, затем сложение/вычитание, затем сравнения, затем И, в конце — Или. Сомневаетесь в приоритете — ставьте скобки: они не влияют на производительность, но делают намерение явным.
| Приоритет | Операторы | Пример |
|---|---|---|
| 1 (высший) | Не, унарный минус | Не Флаг, -Сумма |
| 2 | , /, % | Цена Количество |
| 3 | +, − | Сумма + НДС |
| 4 | =, <>, >, <, >=, <= | Итог > 0 |
| 5 | И | Усл1 И Усл2 |
| 6 (низший) | Или | Усл1 Или Усл2 |
Выражение «А И Б Или В» вычисляется как «(А И Б) Или В», а не «А И (Б Или В)» — это частый источник логических ошибок в сложных условиях.
Как проверить результат
Конфигуратор не сообщает об ошибках синтаксиса при проверке модуля
Сообщения о незакрытых операторных скобках или неизвестных именах
При тесте на граничных значениях (0, пустая ссылка, Неопределено) результат совпадает с ожидаемым
Ветка Иначе срабатывает там, где должна сработать основная
Цикл завершается за предсказуемое время, все элементы обработаны
Зависание сеанса или пропущенные строки коллекции
Ошибка попадает в журнал регистрации с понятным текстом
Ошибка «проглатывается», в журнале пусто
Практический порядок освоения
Начните с присваивания и простых арифметических операций в консоли кода или внешней обработке. Затем добавьте условия и цикл Для Каждого по таблице значений — это покрывает большую часть повседневных задач доработки типовых конфигураций.
- 1Создайте внешнюю обработку и в модуле формы напишите простое присваивание и вывод через Сообщить()
- 2Добавьте условие Если с проверкой значения и веткой Иначе
- 3Организуйте цикл Для Каждого по таблице значений с накоплением суммы
- 4Оберните потенциально опасное вычисление в Попытка...Исключение с записью в журнал регистрации
- 5Проверьте поведение на граничных значениях: 0, пустая строка, Неопределено
Что важно запомнить
Один знак = служит и присваиванием, и сравнением; типы приводите явно; цикл Пока требует гарантированного выхода; ошибки перехватывайте через Попытка с обязательным журналированием; при сомнениях в приоритете ставьте скобки.
Частые вопросы
Чем отличается Неопределено от NULL в 1С?
Неопределено — значение встроенного языка, означающее отсутствие данных (например, незаполненный параметр). NULL появляется только в результатах запросов при левом соединении или отсутствующих полях. Они не равны друг другу, и NULL нужно обрабатывать функцией ЕСТЬNULL() прямо в запросе.
Можно ли использовать && и || вместо И и Или?
Нет, встроенный язык 1С не поддерживает такие сокращения. Используйте ключевые слова И, Или, Не — в русском или английском синтаксисе (And, Or, Not), но не символы из C-подобных языков.
Как выйти сразу из двух вложенных циклов?
Оператор Прервать действует только на ближайший цикл. Варианты: установить флаг и проверить его во внешнем цикле, вынести оба цикла в функцию и использовать Возврат, либо вызвать и перехватить исключение (последний способ считается плохой практикой для обычной логики).
Почему сложение числа и строки вызывает ошибку?
Встроенный язык не выполняет неявное преобразование между числом и строкой в арифметических операциях. Приведите значение явно: Строка(ЧислоЗначение) для конкатенации или Число(СтрокаЗначение) для вычисления, предварительно убедившись, что строка содержит корректное число.
Работает ли оператор ?() на сервере и на клиенте?
Да, тернарный оператор ?(Условие, Значение1, Значение2) доступен в любом контексте выполнения — тонкий клиент, веб-клиент, сервер. Ограничений по директивам компиляции у него нет.
Какой цикл быстрее: Для или Для Каждого?
Для обхода коллекций предпочтителен Для Каждого — он читаемее и не требует обращения по индексу. Разница в скорости на типовых объёмах данных несущественна; реальные потери производительности обычно связаны с запросами внутри цикла, а не с выбором конструкции обхода.