Должен ли я использовать `! IsGood` или` IsGood == false`? - PullRequest
46 голосов
/ 10 декабря 2008

Я постоянно вижу код, который проверяет, как это

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

или это

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

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

if (IsGood)
{
   DoSomething();
}

или

if (!IsGood)
{
   DoSomething();
}

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

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

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

Ответы [ 41 ]

104 голосов
/ 10 декабря 2008

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

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

38 голосов
/ 10 декабря 2008

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

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

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

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

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

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

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

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

32 голосов
/ 10 декабря 2008

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

Для реальных сценариев в проектах, использующих C # 2.0, я вижу только одну вескую причину сделать это: bool? type. Трехуровневое 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!");
                }
            }
        }
    }
}

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

18 голосов
/ 10 декабря 2008

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

if (IsGood)
if (!IsGood)

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

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

  • IsGood
  • HasValue
  • и т.д.
15 голосов
/ 10 декабря 2008

Техника тестирования специально против 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 #, которые не позволяют использовать интегральное значение в качестве логического значения.

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

13 голосов
/ 10 декабря 2008

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

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

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

9 голосов
/ 10 декабря 2008

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

if(IsGood) DoSomething();

или

if(IsBad == false) DoSomething();

вместо

if(!IsBad) DoSomething();

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

7 голосов
/ 10 декабря 2008

Судя по ответам, это, похоже, консенсус:

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

Только для чтения ..

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

6 голосов
/ 10 декабря 2008

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

if (IsGood)
{
    DoSomething();
}

и

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

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

...