Should I use `!IsGood` or `IsGood == false`?

Solution 1:

I follow the same syntax as you, it's less verbose.

People (more beginner) prefer to use == true just to be sure that it's what they want. They are used to use operator in their conditional... they found it more readable. But once you got more advanced, you found it irritating because it's too verbose.

Solution 2:

I always chuckle (or throw something at someone, depending on my mood) when I come across

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

because surely if you can't rely on the fact that your comparison returns a boolean, then you can't rely on comparing the result to true either, so the code should become

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

but, of course, this should really be

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

but, of course ...

(ah, compilation failed. Back to work.)

Solution 3:

I would prefer shorter variant. But sometimes == false helps to make your code even shorter:

For real-life scenario in projects using C# 2.0 I see only one good reason to do this: bool? type. Three-state bool? is useful and it is easy to check one of its possible values this way.

Actually you can't use (!IsGood) if IsGood is bool?. But writing (IsGood.HasValue && IsGood.Value) is worse than (IsGood == true).

Play with this sample to get idea:

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");
}

There is one more case I've just discovered where if (!IsGood) { ... } is not the same as if (IsGood == false) { ... }. But this one is not realistic ;) Operator overloading may kind of help here :) (and operator true/false that AFAIK is discouraged in C# 2.0 because it is intended purpose is to provide bool?-like behavior for user-defined type and now you can get it with standard type!)

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!");
                }
            }
        }
    }
}

So... please, use operator overloading with caution :(

Solution 4:

According to Code Complete a book Jeff got his name from and holds in high regards the following is the way you should treat booleans.

if (IsGood)
if (!IsGood)

I use to go with actually comparing the booleans, but I figured why add an extra step to the process and treat booleans as second rate types. In my view a comparison returns a boolean and a boolean type is already a boolean so why no just use the boolean.

Really what the debate comes down to is using good names for your booleans. Like you did above I always phrase my boolean objects in the for of a question. Such as

  • IsGood
  • HasValue
  • etc.

Solution 5:

The technique of testing specifically against true or false is definitely bad practice if the variable in question is really supposed to be used as a boolean value (even if its type is not boolean) - especially in C/C++. Testing against true can (and probably will) lead to subtle bugs:

These apparently similar tests give opposite results:

// 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;
}

This displays the following result:

isGood != true
isGood is true

If you feel the need to test variable that is used as a boolean flag against true/false (which shouldn't be done in my opinion), you should use the idiom of always testing against false because false can have only one value (0) while a true can have multiple possible values (anything other than 0):

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

Some people will have the opinion that this is a flaw in C/C++, and that may be true. But it's a fact of life in those languages (and probably many others) so I would stick to the short idiom, even in languages like C# that do not allow you to use an integral value as a boolean.

See this SO question for an example of where this problem actually bit someone...

  • isalpha() == true evaluates to false??