Как правильно использовать оператор присваивания в 1С и почему не работают цепочки присваивания

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При переходе на платформу 1С:Предприятие разработчики, имеющие опыт работы с языками семейства C (C++, C#, Java, JavaScript), часто сталкиваются с неожиданным поведением базовых операторов. Одним из таких камней преткновения становится оператор присваивания. В этой статье мы подробно разберем, почему привычные конструкции вида А = Б = В в 1С работают не так, как ожидается, и как правильно писать код, чтобы избежать логических ошибок.

Анализ проблемы: почему цепочка присваивания не работает?

Рассмотрим ситуацию, описанную автором вопроса. Программист пытается в одну строку установить свойство Доступность для двух элементов формы:


Элементы.ПересчитыватьЦены.Доступность = Элементы.ПроцентПересчетаЦены.Доступность = Ложь;

В языках вроде C++ такая запись означала бы, что сначала переменной Элементы.ПроцентПересчетаЦены.Доступность присваивается значение Ложь, а затем результат этой операции (то есть тоже Ложь) присваивается переменной Элементы.ПересчитыватьЦены.Доступность. В итоге оба элемента стали бы недоступны.

Однако в 1С результат будет иным. Проанализируем, как интерпретатор 1С читает эту строку. В языке 1С символ = выполняет две принципиально разные роли: оператора присваивания и оператора сравнения. Логика парсера системы такова:

  1. Первый встреченный символ = в инструкции (если это не условие Если или Пока) всегда считается оператором присваивания.
  2. Все последующие символы = в этой же строке интерпретируются как логические операторы сравнения ("Равно").

Таким образом, выражение превращается в следующую логическую конструкцию:

Переменная_1 = (Переменная_2 = Значение)

Сначала вычисляется правая часть: Элементы.ПроцентПересчетаЦены.Доступность = Ложь. Это логическое выражение. Если свойство Доступность в данный момент равно Истина, то результат сравнения будет Ложь. Если свойство уже было равно Ложь, то результат сравнения будет Истина. Затем этот булев результат (Истина или Ложь) присваивается первому элементу. В итоге мы получаем не массовое присваивание значения Ложь, а непредсказуемое изменение состояния первого элемента в зависимости от текущего состояния второго.

Отсутствие возвращаемого значения при присваивании

Выясним фундаментальную причину, почему поведение 1С отличается от C-образных языков. В C++ присваивание является выражением, которое возвращает присвоенное значение. Это позволяет вкладывать присваивания друг в друга.

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

Как правильно реализовать множественное присваивание

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


// Устанавливаем доступность для первого элемента
Элементы.ПересчитыватьЦены.Доступность = Ложь;

// Устанавливаем доступность для второго элемента
Элементы.ПроцентПересчетаЦены.Доступность = Ложь;

Хотя такой код занимает больше строк, он обладает неоспоримыми преимуществами:

Другие ограничения синтаксиса: инкремент и декремент

Рассмотрим еще один важный момент, упомянутый в обсуждении — отсутствие операторов i++ или i--. В 1С нельзя использовать краткие формы изменения значения переменной, такие как +=, -= или ++. Посмотрим на примере, как нужно изменять счетчик:


// Вместо привычного сишникам i++;
Счетчик = Счетчик + 1;

// Вместо Сумма += Цена;
Сумма = Сумма + Цена;

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

Нюансы сравнения в правой части выражения

Поскольку мы выяснили, что вторая часть выражения А = Б = В является логическим сравнением, важно помнить, как именно 1С сравнивает данные различных типов, чтобы не получить неожиданный результат Ложь:

  1. Сравнение строк: 1С игнорирует незначащие пробелы в конце строки. Например, "Склад" = "Склад " вернет Истина.
  2. Сравнение ссылок: при сравнении объектов (например, элементов справочника) система сравнивает их уникальные идентификаторы (ссылки), а не содержимое их реквизитов.
  3. Разные типы: сравнение значений разных типов (например, числа 0 и значения Ложь) в 1С всегда дает Ложь, в отличие от JavaScript, где типы могут приводиться друг к другу.

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

← На главную