Должен ли я использовать `!IsGood` или`IsGood == false`?

Я продолжаю видеть код, который делает проверки, как это

if (IsGood == false)
{
   DoSomething();
}

или это

if (IsGood == true)
{
   DoSomething();
}

Я ненавижу этот синтаксис и всегда использую следующий синтаксис.

if (IsGood)
{
   DoSomething();
}

или же

if (!IsGood)
{
   DoSomething();
}

Есть ли причина использовать== true' или же '== false"?

Это удобочитаемость? Люди просто не понимают булевых переменных?

Кроме того, есть ли разница в производительности между этими двумя?

41 ответ

Решение

Я придерживаюсь того же синтаксиса, что и вы, он менее многословен.

Люди (больше начинающих) предпочитают использовать == true просто чтобы быть уверенным, что это то, что они хотят. Они привыкли использовать оператор в своих условных выражениях... они нашли его более читабельным. Но как только вы стали более продвинутым, вы почувствовали раздражение, потому что это слишком многословно.

Я всегда хихикаю (или бросаю что-то в кого-то, в зависимости от моего настроения), когда сталкиваюсь

if (someBoolean == true) { /* ... */ }

потому что, конечно, если вы не можете полагаться на тот факт, что ваше сравнение возвращает логическое значение, то вы также не можете полагаться на сравнение результата с истинным, поэтому код должен стать

if ((someBoolean == true) == true) { /* ... */ }

но, конечно, это действительно должно быть

if (((someBoolean == true) == true) == true) { /* ... */ }

но конечно...

(Ах, сборка не удалась. Вернуться к работе.)

Я бы предпочел более короткий вариант. Но иногда == false помогает сделать ваш код еще короче:

Для реальных сценариев в проектах, использующих C# 2.0, я вижу только одну хорошую причину сделать это: bool? тип. Три состояния bool? полезен, и таким образом легко проверить одно из его возможных значений.

На самом деле вы не можете использовать (!IsGood) если IsGood является bool?, Но писать (IsGood.HasValue && IsGood.Value) хуже чем (IsGood == true),

Поиграйте с этим примером, чтобы получить представление:

bool? value = true; // try false and null too

if (value == true)
{
    Console.WriteLine("value is true");
}
else if (value == false)
{
    Console.WriteLine("value is false");
}
else
{
    Console.WriteLine("value is null");
}

Есть еще один случай, который я только что обнаружил, где if (!IsGood) { ... } это не то же самое, что if (IsGood == false) { ... }, Но этот нереалистичен;) Перегрузка операторов может здесь помочь:) (и оператор true/false, что AFAIK не рекомендуется в C# 2.0, потому что его предназначение состоит в том, чтобы обеспечить поведение типа bool? Для пользовательского типа и теперь Вы можете получить это со стандартным типом!)

using System;

namespace BoolHack
{
    class Program
    {
        public struct CrazyBool
        {
            private readonly bool value;

            public CrazyBool(bool value)
            {
                this.value = value;
            }

            // Just to make nice init possible ;)
            public static implicit operator CrazyBool(bool value)
            {
                return new CrazyBool(value);
            }

            public static bool operator==(CrazyBool crazyBool, bool value)
            {
                return crazyBool.value == value;
            }

            public static bool operator!=(CrazyBool crazyBool, bool value)
            {
                return crazyBool.value != value;
            }

            #region Twisted logic!

            public static bool operator true(CrazyBool crazyBool)
            {
                return !crazyBool.value;
            }

            public static bool operator false(CrazyBool crazyBool)
            {
                return crazyBool.value;
            }

            #endregion Twisted logic!
        }

        static void Main()
        {
            CrazyBool IsGood = false;

            if (IsGood)
            {
                if (IsGood == false)
                {
                    Console.WriteLine("Now you should understand why those type is called CrazyBool!");
                }
            }
        }
    }
}

Так что... пожалуйста, используйте перегрузку оператора с осторожностью:(

Согласно книге " Завершить код", Джефф получил свое имя и высоко ценит следующее. Вот как вы должны обращаться с логическими значениями.

if (IsGood)
if (!IsGood)

Я обычно сравниваю логические значения, но я решил, зачем добавлять дополнительный шаг к процессу и рассматривать логические значения как второсортные типы. На мой взгляд, сравнение возвращает логическое значение, а логический тип уже является логическим, так почему бы просто не использовать логическое значение.

На самом деле спор сводится к использованию хороших имен для ваших логических выражений. Как вы делали выше, я всегда формулирую свои логические объекты в вопросе. Такие как

  • Это хорошо
  • HasValue
  • и т.п.

Техника тестирования специально против true или false определенно является плохой практикой, если рассматриваемая переменная действительно должна использоваться как логическое значение (даже если ее тип не является логическим), особенно в C/C++. Тестирование против true может (и, вероятно, приведет) к тонким ошибкам:

Эти явно похожие тесты дают противоположные результаты:

// needs C++ to get true/false keywords
// or needs macros (or something) defining true/false appropriately
int main( int argc, char* argv[])
{
    int isGood = -1;

    if (isGood == true) {
        printf( "isGood == true\n");
    }
    else {
        printf( "isGood != true\n");
    }

    if (isGood) {
        printf( "isGood is true\n");
    }
    else {
        printf( "isGood is not true\n");
    }

    return 0;
}

Это отображает следующий результат:

isGood != true
isGood is true

Если вы чувствуете необходимость проверить переменную, которая используется в качестве логического флага, против true/false (что, по моему мнению, не следует делать), вы должны использовать идиому всегда проверять против false, потому что false может иметь только одно значение (0) в то время как истина может иметь несколько возможных значений (все, кроме 0):

if (isGood != false) ...  // instead of using if (isGood == true)

Некоторые люди будут считать, что это недостаток C/C++, и это может быть правдой. Но это факт жизни в этих языках (и, вероятно, во многих других), поэтому я бы придерживался краткой идиомы, даже в таких языках, как C#, которые не позволяют использовать интегральное значение в качестве логического значения.

Посмотрите этот ТАК вопрос для примера, где эта проблема на самом деле кого-то кусала...

Я согласен с вами (и меня это тоже раздражает). Я думаю, что это лишь небольшое недопонимание того, что IsGood == true оценивает bool, который является то, что IsGood должен был начать с.

Я часто вижу эти близкие случаи SomeStringObject.ToString(),

Тем не менее, в языках, которые играют слабее с типами, это может быть оправдано. Но не в C#.

Некоторые люди считают, что явная проверка по известному значению более удобочитаема, так как вы можете определить тип переменной, прочитав. Я агностик относительно того, лучше ли один, чем другой. Они оба работают. Я считаю, что если переменная по своей сути содержит "инверсию", то я, кажется, тяготею к проверке значения:

if(IsGood) DoSomething();

или же

if(IsBad == false) DoSomething();

вместо

if(!IsBad) DoSomething();

Но опять же, это не имеет большого значения для меня, и я уверен, что это в конечном итоге, как тот же IL.

Только читабельность..

Во всяком случае, то, что вы предпочитаете, более эффективно при компиляции в машинный код. Однако я ожидаю, что они производят точно такой же машинный код.

Из ответов до сих пор, это, кажется, консенсус:

  1. Краткая форма лучше всего подходит в большинстве случаев. (IsGood и!IsGood)
  2. Булевы переменные должны быть записаны как положительные. (IsGood вместо IsBad)
  3. Поскольку большинство компиляторов будут выводить один и тот же код в любом случае, разницы в производительности нет, за исключением случаев интерпретируемых языков.
  4. Эта проблема не имеет явного победителя, вероятно, можно рассматривать как битву в религиозной войне в стиле кодирования.

Я предпочитаю использовать:

if (IsGood)
{
    DoSomething();
}

а также

if (IsGood == false)
{
    DoSomething();
}

как я нахожу это более читабельным! слишком легко пропустить (как при чтении, так и при наборе текста); также "если не IsGood тогда..." просто не звучит правильно, когда я слышу это, в отличие от "если IsGood ложно тогда...", что звучит лучше.

Я видел следующее как требование стиля C/C++.

if ( true == FunctionCall()) {
  // stuff
}

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

Возможно (хотя и маловероятно, по крайней мере, я надеюсь), что в коде C TRUE и FALSE # определены для вещей, отличных от 1 и 0. Например, программист, возможно, решил использовать 0 как "true" и -1 как "false "в конкретном API. То же самое относится и к унаследованному коду C++, поскольку "true" и "false" не всегда были ключевыми словами C++, особенно в тот день, когда существовал стандарт ANSI.

Стоит также отметить, что некоторые языки, особенно такие, как Perl, JavaScript и PHP, могут по-разному интерпретировать, какие значения считаются истинными, а какие - ложными. Возможно (хотя, опять-таки, вряд ли на надежде), что "foo == false" означает что-то немного отличное от "! Foo". Этот вопрос помечен как "независимый от языка", и язык может определить оператор ==, чтобы он не работал способами, совместимыми с! оператор.

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

Хорошим примером этого может быть strcmp() C/C++, который возвращает 0, если строки равны, иначе <или> 0, в зависимости от того, где находится различие. Так что вы часто будете видеть:

if(strcmp(string1, string2)==0) { /*do something*/ }

Как правило, однако я согласен с вами, что

if(!isCached)
{
    Cache(thing);
}

понятнее читать.

Только хуже

if (true == IsGood) {....

Никогда не понимал, что стоит за этим методом.

Я предпочитаю подход !IsGood, и я думаю, что большинство людей с языком в стиле c также предпочтут его. Я только догадываюсь здесь, но я думаю, что большинство людей, которые пишут IsGood == False, происходят из более многословного языка, такого как Visual Basic.

Для удобства чтения вы можете рассмотреть свойство, которое зависит от другого свойства:

public bool IsBad => !IsGood;

Тогда вы действительно сможете понять значение:

if (IsBad)
{
    ...
}

!IsGood шаблон легче найти, чем IsGood == false когда сводится к регулярному выражению.

/\b!IsGood\b/

против

/\bIsGood\s*==\s*false\b/
/\bIsGood\s*!=\s*true\b/
/\bIsGood\s*(?:==\s*false|!=\s*true)\b/

Я предпочитаю !IsGood потому что для меня это понятнее и понятнее. Проверка, если boolean == true Это избыточно, поэтому я бы этого избегал. Синтаксически, хотя я не думаю, что есть разница, если проверка IsGood == false,

Ты забыл:

if (IsGood == FileNotFound)

Во многих языках разница в том, что в одном случае компилятор / интерпретатор диктует значение true или false, а в другом случае это определяется кодом. C является хорошим примером этого.

if (something) ...

В приведенном выше примере "что-то" сравнивается с определением компилятора "true". Обычно это означает "не ноль".

if (something == true) ...

В приведенном выше примере "что-то" сравнивается с "истиной". Тип "истина" (и, следовательно, сопоставимость) и значение "истина" могут определяться или не быть определены языком и / или компилятором / интерпретатором.

Часто эти два не совпадают.

Если вы работаете в Perl, у вас есть возможность

unless($isGood)

Мне почему-то всегда нравилось

if (IsGood)

больше, чем

if (!IsBad)

и вот почему я вроде как Руби, если (но это слишком легко злоупотреблять):

unless (IsBad)

и даже больше, если используется так:

raise InvalidColor unless AllowedColors.include?(color)

Лично я предпочитаю форму, о которой говорит дядя Боб в Чистом коде:

(...)
    if (ShouldDoSomething())
    {
        DoSomething();
    }
(...)

bool ShouldDoSomething()
{
    return IsGood;
}

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

Мне кажется (хотя у меня нет доказательств, подтверждающих это), что люди, начинающие на языках типов C#/java, предпочитают метод "if (CheckSomething())", тогда как люди, начинающие на других языках (C++: конкретно Win32) C++) склонны использовать другой метод по привычке: в Win32 "if (CheckSomething())" не будет работать, если CheckSomething возвращает BOOL (вместо bool); и во многих случаях функции API явно возвращают 0/1 int/INT, а не значение true/false (то есть, что такое BOOL).

Я всегда использовал более многословный метод, опять же, по привычке. Они синтаксически одинаковы; Я не покупаю ерунду "многословие раздражает меня", потому что программист не тот, кто должен быть впечатлен кодом (компьютер делает). И в реальном мире уровень квалификации любого конкретного человека, смотрящего на написанный мною код, будет варьироваться, и у меня нет времени или желания объяснять особенности оценки высказываний тому, кто не может понять немного неважно такие биты

Я не использую == но иногда я использую != потому что это более ясно в моей голове. НО на моей работе мы не используем != или же ==, Мы пытаемся получить имя, которое значимо, если с hasXYZ() или же isABC(),

Cybis, при кодировании на C++ вы также можете использовать ключевое слово not. Это часть стандарта с давних времен, так что этот код совершенно действителен:

if (not foo ())
   bar ();

Изменить: Кстати, я забыл упомянуть, что стандарт также определяет другие логические ключевые слова, такие как и (&&), bitand (&) или (||), bitor (|), xor (^)... Они называются оператором синонимы.

Если вы действительно думаете, что вам нужно:

if (Flag == true)

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

if ((Flag == true) == true)

и так далее. Сколько еще гвоздей нужно этому гробу?

Ах, у меня есть кое-что в пользу более длинной формы, утверждая, что она более читаема, чем крошечная!

Я начал "исправлять" это, так как булевы значения самодостаточны, тогда я отбросил крестовый поход... ^_^ В любом случае, им здесь не нравится очистка кода, утверждая, что это затрудняет интеграцию между ветвями (это правда, но тогда ты вечно живешь с плохо выглядящим кодом...).

Если вы правильно пишете имя вашей логической переменной, оно должно выглядеть так:
if (isSuccessful) против if (returnCode)

Я мог бы заниматься булевым сравнением в некоторых случаях, например:
if (PropertyProvider.getBooleanProperty(SOME_SETTING, true) == true) потому что он читает меньше "естественно".

Эти две формы семантически идентичны и производят один и тот же машинный код, так почему бы не использовать ту, которая более читаема?

if (IsGood == false) лучше, чем if(!IsGood),

При сканировании кода легко ошибиться "!" предшествующая переменная bool для символа в переменной bool.

В языке, подобном C, где нет типа "Boolean", я рекомендую более длинный путь, т.е.

if (is_good == True)
{
}

Причина в том, что это хорошо не только true/false (скорее всего, реализовано как символ) и, следовательно, может быть повреждено другими значениями или неправильно установлено.

Так что же хорошего в этом? Ваш код сможет подобрать любые проблемы с is_good быть установленным неправильно, потому что без проверки == True или == False все будет означать true;) И если вы действительно имеете в виду логическое значение, то это плохо.

Другие вопросы по тегам