0

Также возможно использование условия if(1 || !Foo())?

8

Я наткнулся на устаревший код:

if ( 1 || !Foo() )

Мне не совсем понятно, есть ли причина использовать такую конструкцию вместо более простой:

if ( !Foo() )

Неужели кто-то действительно считает, что первый вариант может иметь преимущества? Или это просто остатки от старого кода, который не был должным образом переработан? Буду благодарен за любые пояснения!

3 ответ(ов)

1

Два варианта не одинаковы. Первый вариант никогда не выполнит Foo(), потому что 1 вызывает краткую подстановку в выражении ||.

Почему это сделано — возможно, кто-то хотел заставить программу войти в ветвь then для целей отладки и оставил это там. Также может быть, что этот код был написан до появления систем контроля версий, и разработчик не хотел, чтобы код потерялся, а просто временно оставил его в обходе.

0

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

int c = 5;
if (1 || c++){}
printf("%d", c);

Вывод будет 5, поскольку c никогда не увеличивается. Однако если заменить 1 на 0, то c++ будет действительно вызван, в результате чего вывод будет равен 6.


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

if (1 || condition) {
    // код, который я хочу протестировать
}

Таким образом, condition никогда не будет оцениваться, и, следовательно, код под комментарием // код, который я хочу протестировать всегда будет выполнен. Однако это определенно не то же самое, что:

if (condition) { ...

В этом случае condition действительно будет проверено, и в вашем примере Foo будет вызван.

0

Вопрос был корректно отвечен – разница заключается в том, что правая часть операции or (или) подлежит укороченному вычислению, что указывает на то, что это код для отладки, предназначенный для принудительного входа в блок if.

Тем не менее, в интересах соблюдения лучших практик, я бы предложил альтернативы, в порядке увеличения предпочтительности (лучшее решение будет последним):

Примечание: Я заметил после написания примеров, что вопрос был о C++, а примеры на C#. Надеюсь, вы сможете адаптировать их. Если кому-то нужно – просто оставьте комментарий.

Инлайн-комментарий:

if (1 /*условие*/) //временная отладка

Выносимый комментарий:

//if(условие)
if(true) //временная отладка

Функция с индикативным именем:

//в некотором общем контейнере
bool ForceConditionForDebug(bool forcedResult, string IgnoredResult)
{
      #if DEBUG
          Debug.WriteLine(
              string.Format(
                  "Условие {0} принудительно изменено на {1} для целей отладки",
                  IgnoredResult,
                  forcedResult));
          return forcedResult;
      #else
          #if ALLOW_DEBUG_CODE_IN_RELEASE
              return forcedResult;
          #else
              throw new ApplicationException("Обнаружен код отладки в режиме релиза");
          #endif
      #endif
}

//Где используется
if(ForceConditionForDebug(true, "условие"))...

//Наш случай
if(ForceConditionForDebug(true, "!Foo()"))...

И если вам нужно действительно надежное решение, вы можете добавить правило репозитория в систему контроля версий, чтобы отклонять любой код, который вызывает ForceConditionForDebug. Этот код никогда не должен был быть написан таким образом, потому что он явно не передает намерение. Его ни в коем случае не следовало проверять (или допускать к проверке) (контроль версий? рецензирование кода?). И его точно нельзя допускать к выполнению в продакшене в текущем виде.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь