我应该使用`!IsGood`还是`IsGood == false`?

48

我经常看到像这样进行检查的代码

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

或者这个

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

我讨厌这种语法,总是使用以下语法。

if (IsGood)
{
   DoSomething();
}
或者
if (!IsGood)
{
   DoSomething();
}

使用 '== true' 或 '== false' 有什么理由吗?

这是为了可读性吗?人们只是不理解布尔变量吗?

此外,这两者之间是否存在性能差异?


14
如果这件事真的让你如此困扰,那么你的生活会变得漫长而艰辛。 - GEOCHET
4
这是一个公平的问题,对我来说,提问者似乎并不太生气。 - annakata
是的,它是有效的。我有时会对简单的事情产生怀疑,并偶尔找到改变自己方式的好理由... - Michael Haren
1
Chris,这不是分支结构的问题。C是有类型的语言,但它没有布尔类型。"if(good)"与"if(good == TRUE)"是不同的。前者意味着good非零。后者意味着good恰好等于TRUE,即一个特定的整数值。请查看MikeB的答案以获取更多信息。 - Jim Nelson
7
我认为的主要问题是,这会让开发人员显得不太理解布尔值。 - JoelFan
显示剩余6条评论
41个回答

103

我使用与您相同的语法,它更简洁。

有些人(尤其是初学者)倾向于使用== true,只是为了确保他们想要的结果。他们习惯于在条件语句中使用运算符...他们发现这样更易读。但是一旦你变得更加高级,你会觉得这很烦人,因为它太冗长。


@litb:我知道这是我第一次看到投票速度如此之快:P在过去的20分钟里,它获得了大约15票。令人惊讶。 - Patrick Desjardins
3
如果你给变量起合适的名字,那么添加运算符实际上会降低可读性。例如,"if is good" 比 "if is good is true" 更易读。我选择使用 "if (isGood)" ,这样就清晰明了了。 - Marko Dumic
@Christopher:除非你写成"true == myVar"或者"false == myVar",否则你会遇到一些微妙的错误,比如"if (myVar = true) {}"。 - GalacticCowboy
9
这个网站简直失控了,一个几乎无关紧要的观点居然收到了56个投票? - JC.
5
当我看到布尔类型使用 == 时,我认为这表明使用 == 的人完全理解布尔逻辑及其含义。 - Lara Dougan
显示剩余8条评论

39

当我遇到以下内容时,我总是会笑(或者根据我的心情扔东西)

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

因为如果你不能依赖于比较返回一个布尔值的事实,那么你也不能依赖于将结果与true进行比较,所以代码应该变成:

因为如果你不能依靠比较返回布尔值这一事实,那么你也无法依靠将结果与true进行比较。因此,代码应该改为:

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

但是,当然,这确实应该是

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

当然了,编译失败了。回去继续工作吧。


3
蒙提·派森和《垃圾邮件》小品的影子......我想要一个使用 Spam、Spam、Spam、true 和 Spam 的 If 测试。 - Ken Ray

32

我更喜欢较短的变量名。但是有时候使用== false可以使你的代码变得更短:

在使用C# 2.0的实际项目中,我只看到一个很好的理由来这样做:bool? 类型。三态bool? 很有用,使用这种方式很容易检查其中一种可能的值。

实际上,如果IsGoodbool?类型,你无法使用 (!IsGood)。但是,写(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) { ... }并不相同。但这种情况不太现实;) 运算符重载可能有所帮助:)(而且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!");
                }
            }
        }
    }
}

所以...请小心使用运算符重载 :(


如果IsGood是可空布尔值,则(IsGood == true)也不起作用。你必须写(IsGood.HasValue && IsGood.Value == true),这仍然比(IsGood.HasValue && IsGood.Value)更冗长、更难以理解。 - Charles Bretana
1
Charles,第一个示例适用于三种情况(当IsGood类型为bool?时,它被初始化为true、false或null)。我又检查了一遍。您是说第一个示例将不会使用C# 2.0编译器进行编译吗?实际上是可以的...即使在null情况下也没有异常 :) - IgorK
我真的很怀疑,但我会自己尝试一下;p - Shawn
如果你想这么做,请使用(false == value)而不是(value == false),因为你可能会搞砸并意外地写成(value = false),这可能会或可能不会导致编译器警告。 - Mehrdad Afshari
1
我更喜欢使用 if(IsGood.GetValueOrDefault()),它与 if(IsGood.HasValue && IsGood.Value) 产生相同的效果并且更快(执行时间)。请注意,if(!IsGood.GetValueOrDefault()) 与 if(IsGood.HasValue && !IsGood.Value) 不同。 - P Daddy
显示剩余5条评论

18

根据《代码大全》(Code Complete)这本书,Jeff命名并高度评价该书,以下是您应该处理布尔值的方式。

if (IsGood)
if (!IsGood)

我曾经使用实际比较布尔值的方法,但后来想到为什么要增加一个额外的步骤并将布尔类型视为次等类型。在我看来,比较返回一个布尔值,而布尔类型本身就是一个布尔值,所以为什么不直接使用布尔值呢。

真正的争论在于给你的布尔值取好名字。像你上面做的那样,我总是用问题形式来表达我的布尔对象。例如

  • IsGood(好的吗)
  • HasValue(有价值吗)
  • 等等。

15

如果变量在实际中应该被用作布尔值(即使其类型不是布尔值),那么专门针对真或假进行测试的技术绝对是一种不好的做法 - 尤其是在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),而true可以具有多个可能的值(除了0以外的任何值):

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

有些人认为这是C/C++的缺陷,这可能是正确的。但这是这些语言(以及可能许多其他语言)中的生活事实,因此我会坚持使用简短的习惯用语,即使在像C#这样的语言中,您也无法将整数值用作布尔值。

请参阅此SO问题,了解此问题实际上影响了某些人的示例...


13

我同意你的观点(并且也感到烦恼)。我认为这只是一种轻微的误解,即IsGood == true会被评估为bool,而IsGood本来就是如此。

我经常看到类似于SomeStringObject.ToString()的实例。

尽管如此,在那些类型更松散的语言中,这可能是合理的。但在C#中不是这样。


这个观点很好,它出现在String.ToString()附近,但我很想知道是否对于一些习惯于数据类型较松的语言的开发人员来说,这可能是一种习惯力量的体现。 - rjzii
关于它评估为布尔值的真实性,这是您开始的地方。那么你在哪里停止呢?((isGood == false) == true)?不,那也是一个布尔值,((((isGood == false) == true) == true)等等...将布尔值与布尔值进行比较只意味着您做错了... :p - jalf

9

有些人认为明确检查已知值更易于阅读,因为您可以通过阅读来推断变量类型。我对哪种方法更好持中立态度。它们都有效。如果变量本质上保持“反向”,那么我似乎倾向于检查值:

if(IsGood) DoSomething();

或者

if(IsBad == false) DoSomething();

替代

if(!IsBad) DoSomething();

但是对我来说并不重要,我相信最终它会变成相同的 IL。


这是我的做法。如果我想查找 false,我会使用 == false,但我尽量避免这样做。实际上,我更愿意根本不反转条件语句。通常通过重新构造 isBad 为 isGood 或者交换 if/else 块等方式更有道理。 - Adam Jaskiewicz
如果你看到if(IsGood),你也可以推断它是一个布尔类型,否则它就不会编译!;) 不管怎样,你是对的,初学者往往以这种方式更清晰明了。 - rgargente

7

仅供阅读..

如果有的话,你偏爱的方式在编译为机器代码时更为高效。然而,我预计它们会产生完全相同的机器代码。


7

从迄今为止的答案来看,这似乎是共识:

  1. 在大多数情况下,短表达方式最好。(IsGood和!IsGood)
  2. 布尔变量应该写成肯定形式。(IsGood而不是IsBad)
  3. 由于大多数编译器都会输出相同的代码,所以除了解释性语言之外,没有性能差异。
  4. 这个问题没有明显的赢家,可能被视为编码风格宗教战争中的一场战斗。

4
我不同意没有明显优势的说法,特别是在C/C++中。这不仅涉及到风格问题,也可能存在语义差异。使用更长的形式可能会导致微妙的错误。 - Michael Burr
但是使用更长的形式可能会导致微妙的错误。只需使用“!”就可以避免像“if (isGood = false)”这样的错误。 - AustinWBryan

6

我更喜欢使用:

if (IsGood)
{
    DoSomething();
}

并且

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

我认为这样更易读 - 感叹号太容易被忽略了(在阅读和打字时都是如此); 而且“if not IsGood then...”听起来不自然,相比之下,“if IsGood is false then...”听起来更好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接