Почему логическое условие в 1С возвращает Ложь вместо Истины и как работают операторы И, ИЛИ, НЕ

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

При написании программного кода на языке 1С:Предприятие 8 одной из самых частых задач является построение сложных условий с использованием операторов Если и Пока. Однако начинающие разработчики часто сталкиваются с ситуацией, когда, казалось бы, правильно составленное условие работает не так, как ожидалось. Разберем на конкретном примере, почему сочетание нескольких логических выражений может приводить к результату Ложь, и изучим фундаментальные правила работы логических операторов.

Анализ проблемы: почему Ложь И Истина не дает Истину

Проанализируем ситуацию, возникшую у автора темы. В коде было прописано следующее условие:


Если НЕ (Стр.СуммаОборотДт = 0 И Стр.СуммаОборотКт = 0) И (ТипЗнч(Стр.Период2) <> ТипЗнч(Неопределено)) Тогда
    // Какая-то логика
КонецЕсли;

Автор поясняет, что первая часть выражения НЕ (Стр.СуммаОборотДт = 0 И Стр.СуммаОборотКт = 0) вычисляется как Ложь, а вторая часть (ТипЗнч(Стр.Период2) <> ТипЗнч(Неопределено)) — как Истина. Ошибка программиста заключалась в ожидании того, что общее выражение станет истинным. Однако в 1С, как и в классической математической логике, оператор И (конъюнкция) требует, чтобы все части выражения были истинными одновременно.

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

  1. ИСТИНА И ИСТИНА = ИСТИНА (только в этом случае условие сработает).
  2. ИСТИНА И ЛОЖЬ = ЛОЖЬ.
  3. ЛОЖЬ И ИСТИНА = ЛОЖЬ (именно этот случай произошел в примере).
  4. ЛОЖЬ И ЛОЖЬ = ЛОЖЬ.

Таким образом, если хотя бы один из операндов, соединенных оператором И, равен Ложь, то и все выражение целиком будет равно Ложь.

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

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

  1. НЕ (NOT) — имеет наивысший приоритет. Выполняется в первую очередь. Оно инвертирует значение: НЕ Ложь становится Истиной.
  2. И (AND) — средний приоритет. Выполняется после всех отрицаний.
  3. ИЛИ (OR) — самый низкий приоритет. Выполняется в последнюю очередь.

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


// Без скобок логика меняется:
Если НЕ Стр.СуммаОборотДт = 0 И Стр.СуммаОборотКт = 0 Тогда

В данном случае система сначала выполнит НЕ Стр.СуммаОборотДт = 0, а затем результат этой операции свяжет через И со вторым равенством. Использование скобок — это лучший способ явно указать платформе порядок вычислений и сделать код читаемым для других разработчиков.

Особенности ленивых вычислений в 1С

Проанализируем важный нюанс платформы 1С:Предприятие 8, который часто игнорируют. В многих языках программирования (например, в JavaScript или C#) используется механизм "короткого замыкания" (short-circuiting): если в условии А И Б первая часть А оказалась Ложь, то вторая часть Б даже не будет проверяться, так как результат уже предрешен.

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


Если Объект <> Неопределено И Объект.Ссылка.Пустая() Тогда
    // Если Объект все же Неопределено, этот код может вызвать ошибку
    // "Обращение к процедуре объекта как к функции" или "Значение не является значением объектного типа"
КонецЕсли;

Чтобы гарантированно избежать ошибок, мы рекомендуем разделять такие проверки на вложенные условия Если:


Если Объект <> Неопределено Тогда
    Если Объект.Ссылка.Пустая() Тогда
        // Здесь мы в безопасности
    КонецЕсли;
КонецЕсли;

Оптимизация сравнений и чистота кода

Обратим внимание на вторую часть условия автора: ТипЗнч(Стр.Период2) <> ТипЗнч(Неопределено). С точки зрения производительности и стандартов разработки 1С, такая конструкция избыточна. Функция ТипЗнч() требует вычислительных ресурсов для определения типа и получения эталона.

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


// Вместо: ТипЗнч(Стр.Период2) <> ТипЗнч(Неопределено)
// Пишем:
Стр.Период2 <> Неопределено

Результат будет идентичным, но код станет значительно чище.

Использование законов де Моргана для упрощения условий

Сложные конструкции с оператором НЕ и вложенными И/ИЛИ часто трудно читать. Для их упрощения программисты применяют законы де Моргана. Основное правило гласит: отрицание конъюнкции есть дизъюнкция отрицаний.

Разберем это на примере автора. У него было выражение:
НЕ (Стр.СуммаОборотДт = 0 И Стр.СуммаОборотКт = 0)

Применяя закон де Моргана, мы можем переписать его так:
(Стр.СуммаОборотДт <> 0) ИЛИ (Стр.СуммаОборотКт <> 0)

Согласитесь, второй вариант читается гораздо легче: "Если оборот по дебету не равен нулю или оборот по кредиту не равен нулю". Это избавляет от необходимости в уме "переворачивать" логику отрицания, что снижает риск возникновения ошибок при дальнейшей поддержке кода.

Логика и значения типа NULL

В обсуждении на форуме не упоминался тип NULL, однако при работе с данными из запросов он встречается постоянно. Важно помнить, что NULL — это не Ложь и не Истина, а "отсутствие значения".

В условиях Если любые операции, результатом которых является NULL, интерпретируются платформой как Ложь. Однако стоит помнить о нюансах:

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

Подведем итоги

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

  1. Всегда используйте скобки, чтобы явно задать приоритет, даже если вы уверены в порядке выполнения.
  2. Для проверки на Неопределено используйте прямое сравнение Значение <> Неопределено.
  3. Упрощайте сложные конструкции с НЕ, используя законы де Моргана.
  4. Помните, что для оператора И достаточно одного ложного значения, чтобы всё условие стало ложным.
← На главную