如何检查相等?(0 == i)或者(i == 0)

22

好的,我们知道以下两行代码是等价的 -

  1. (0 == i)
  2. (i == 0)

此外,过去鼓励使用第一种方法是因为那样可以让编译器在您意外使用 '=' 而不是 '==' 时给出错误消息。

我的问题是 - 在如今拥有漂亮的IDE和智能编译器的时代,您是否仍然推荐使用第一种方法?

特别是当我看到以下代码时,这个问题突然浮现在我的脑海中 -

if(DialogResult.OK == MessageBox.Show("Message")) ... 

在我看来,我永远不会推荐上述做法。有其他人有不同的意见吗?


这是有关相同问题的另一个讨论: http://www.removingalldoubt.com/permalink.aspx/1d2c1827-9b4d-493e-88ba-10ab27c0dae6 - Marc Gravell
由于这是一个关于C语言的问题,请在此添加C标签。这在C#,Java或Python中并不是一个问题。据我所知,这只是C中的一个开放问题。 - S.Lott
2
对于任何具有==运算符的语言来说,这都是一个风格问题,即使现代语言不会让你混淆i==0和i=0。 - Mark Cidade
@MarkCidade:我不同意这个观点。我认为很难找到有人认为0 == ii == 0更自然。它只是作为避免常见错误的一种方式而出现的。 - Ed S.
你不同意什么?编码风格可能包含一个人认为更自然的方式,也可能更多地与老习惯有关,这取决于程序员。 - Mark Cidade
28个回答

74

我更喜欢第二个选择(i == 0),因为阅读时感觉更符合自然语言习惯。你会问人们,“你是21岁或以上吗?”,而不是“21是否小于或等于你的年龄?”


17
在某些语言中,“21是否小于或等于您的年龄?”是一个更自然的问题。许多编程语言可能看起来有点像英语,但并不是所有程序员都是以英语为母语的。 - James A. Rosen
更不用说你会期望较小的数字先出现了。 - Brad Gilbert
@Spodi:投票数量与查看主题的人数密切相关,如果答案很简单/显然,更多的人会给你点赞。我希望能够因回答关于8086的深奥问题而获得100+票,但可悲的是,很少有人会点击那个主题,甚至更少的人会知道我回答得是否正确。编辑:好吧,我回复了一个四年前的评论... - Ed S.
+1,就我个人而言,我更喜欢比较 variable == constant。我总是将要评估的值写在左侧。我习惯从左到右阅读。如果我写成 = 而不是 ==,那只是因为我没有注意到,需要进行调试。 - Nope
一切都会感觉不自然,直到你习惯了它...有些人会觉得不使用malloc、不使用sizeof *p或不使用函数typedef等都很不自然。 - M.M

21

在C#中,无论您是先放变量还是后放变量都没有关系,因为赋值不会计算为bool(或可转换为bool的内容),所以编译器会捕获任何错误,例如“if(i = 0)EntireCompanyData.Delete()”

因此,在C#世界中,这只是一种风格而不是绝望。将变量放在最后对于英语母语者来说是不自然的。因此,为了使代码更易读,请将变量放在前面。


2
哇,我猜我没有说过那个。不,等等,我有点说过。 - user1228
是的,但你最后得出的结论是“为了更易读的代码,首先定义变量”。 - Nifle
9
好的,我代表“IOnlyReadTheLastSentenceonia”国家接受你对我们的否决。 - user1228
-1 对我来说,这明显是对C/C++的攻击,而不是一个真正的回答。 - PierreBdR
@PierreBdR: :/ 我可以删掉那一部分,但是我会留下一个注释。这是一个合法的注释,变量“first”匹配了人们的说话方式。“你的钱包里有一美元吗?”这种问法非常别扭,问“兄弟能借我一块钱吗?”更为自然。 - user1228
@PierreBdR:你知道吗,我本来想为威尔辩护的,因为我并没有把这当作攻击……直到我注意到这个问题被标记为C和C++。C#的答案在这里有什么相关性呢? - Ed S.

12

如果您有一个if列表不能很好地用switch表示(可能由于语言限制),那么我宁愿看到:

if (InterstingValue1 == foo) { } else
if (InterstingValue2 == foo) { } else
if (InterstingValue3 == foo) { }

因为它可以让您快速查看需要检查的重要值。

特别是在Java中,我发现这样做很有用:

if ("SomeValue".equals(someString)) {
}

因为someString可能为null,这样你就永远不会得到NullPointerException异常。如果您正在比较您知道永远不会为null的常量与可能为null的对象,则同样适用。


9
  1. (0 == i)

我会一直使用这种方式。虽然大多数编译器不允许在条件语句中赋值,但实际上有一些编译器是支持的。在今天的Web编程中,我必须使用很多种语言。通过使用0 == i,我总是知道条件语句将是正确的,而且我不依赖于编译器/解释器来帮我捕捉错误。现在,如果我需要从C#跳到C++或JavaScript,我知道我不必追踪代码中条件语句中的赋值错误。对于一个如此小的事情能够节省这么多时间,这是毫无疑问的。


8

我曾坚信可读性更高的选项 (i == 0) 是更好的选择。

然后我们出现了一个生产错误(不是我的),问题是 ($var = SOME_CONSTANT) 类型的错误。客户开始收到本应发给其他客户的电子邮件,其中包含敏感类型数据。

你可以说 Q/A 应该发现了它,但他们没有,这是另外一个故事。

从那天起,我一直推崇 (0 == i) 版本。它基本上消除了这个问题。虽然它感觉不自然,但你会注意到它,所以你不会犯错。这里根本没有犯错的可能性。

在代码审查中,捕捉到某人没有反转 if 语句要容易得多,而不是某人在 if 中意外赋值。如果格式是编码标准的一部分,人们会寻找它。人们通常不会在代码审查期间调试代码,眼睛似乎会扫过 (i = 0) 和 (i == 0)。

我也更喜欢 Java 的 "Constant String".equals(dynamicString),没有空指针异常是一件好事。


你刚刚让我改变了想法,我现在要转换我的标准。 - Noobification
我的经验与此相反:我看到使用Yoda符号的地方,往往不仅限于可以捕捉= / ==错别字的情况,还包括其他情况,例如if(42 <= result)。 相反符号的增加复杂性会导致出现错误,即使静态检查也无法发现 - 与= / ==场景相反,静态检查是存在的,甚至编辑器现在也可以配置为突出显示这些行。 - Dirk Herrmann

7

你知道,我总是使用 if (i == 0) 这种条件语句的格式,原因是我大部分代码都是用 C# 写的(其他格式也会被标记),而且我采用测试驱动开发方法,我的测试通常会捕捉到这个错误。

我曾经在一些公司工作过,他们试图强制使用 0==i 的格式,但我发现这样写很别扭,容易忘记,而且只会成为代码审查人员寻找低级错误的垃圾代码。


6

实际上,DialogResult示例是我建议采用的样式。它将if()的重要部分放在左侧,这样可以看到它。如果它在右侧并且MessageBox有更多参数(这很可能),您可能需要向右滚动才能看到它。

另一方面,我从未看到"(0 == i)"样式有太多用处。如果您能记住先放常量,那么您也可以记住使用两个等号。


1
说实话,我个人对于那些需要向右滚动才能阅读的代码规则并不感兴趣,因为我会禁止这种情况。你正在测试的东西很重要,对话框的参数也很重要:它们都应该是可见的。 - Steve Jessop
1
我同意你的第二段。 - Steve Jessop
这不是“记得”使用两个等号的问题,而是一个打字错误,编译器无法捕获它,因为它是一个有效的C语言结构。 - Graeme Perrow
@Graeme:当然,但是捕捉拼写错误的一种方法是观察自己输入它们的过程。另一种方法是打开编译器警告。-Wall -Werror,然后就可以了,你的编译器可以捕捉到即使它是有效的C语言 :-) - Steve Jessop
我完全同意警告的观点。你似乎在说“避免打错字的方法就是不打错字”,这并没有什么帮助。 :-) - Graeme Perrow

6

我总是尽量使用第一种情况(0==i),这在几次中曾经拯救了我的生命!


3

我认为这只是一种风格问题。这样做确实有助于避免意外使用赋值运算符。

但我绝对不会要求程序员成熟起来。


3

我使用 (i == 0) 的简单原因是它读起来更好。这在我的脑海中形成了非常流畅的感觉。当你为了调试或其他目的重新阅读代码时,它就像读书一样流畅,更加容易理解。


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