为什么在C#中经常会看到“null!= variable”而不是“variable!= null”?

时间:2008-11-07 08:57:35

标签: c# coding-style

在c#中,你说明这个条件的命令的执行速度有什么不同吗?

if (null != variable) ...
if (variable != null) ...

最近,我经常看到第一个,因为我习惯了第二个,所以引起了我的注意。

如果没有差异,第一个的优势是什么?

9 个答案:

答案 0 :(得分:153)

这是来自C的保留。在C中,如果您使用了错误的编译器或者没有足够高的警告,这将编译时没有任何警告(并且确实是合法代码):

// Probably wrong
if (x = 5)

当你真的可能意味着

if (x == 5)

您可以通过以下方式在C中解决此问题:

if (5 == x)

此处输入错误将导致代码无效。

现在,在C#中,这一切都是piffle。除非你比较两个布尔值(很少见,IME),否则你可以编写更易读的代码,因为“if”语句需要一个布尔表达式来开始,而“x=5”的类型是{ {1}},而不是Int32

我建议,如果你在同事的代码中看到这一点,你就会用现代语言教育他们,并建议他们将来写出更自然的形式。

答案 1 :(得分:12)

首先使用null是有充分理由的:if(null == myDuck)

如果class Duck覆盖了==运算符,则if(myDuck == null)可能会进入无限循环。

首先使用null使用默认的相等比较器并实际执行您想要的操作。

(我听说你习惯于阅读那种最终编写的代码 - 我还没有经历过那种转变)。

以下是一个例子:

public class myDuck
{
    public int quacks;
    static override bool operator ==(myDuck a, myDuck b)
    {
        // these will overflow the stack - because the a==null reenters this function from the top again
        if (a == null && b == null)
            return true;
        if (a == null || b == null)
            return false;

        // these wont loop
        if (null == a && null == b)
            return true;
        if (null == a || null == b)
            return false;
        return a.quacks == b.quacks; // this goes to the integer comparison
    }
}

答案 2 :(得分:9)

我想这是一位已经转换语言的C程序员。

在C中,您可以编写以下内容:

int i = 0;
if (i = 1)
{
    ...
}

注意在那里使用单个等号,这意味着代码将1分配给变量i,然后返回1(赋值是表达式),并在if语句中使用1,它将被处理为真正。换句话说,以上是一个错误。

然而,在C#中,这是不可能的。两者之间确实没有区别。

答案 3 :(得分:8)

就像所有人已经注意到的那样,它或多或少来自C语言,如果你不小心忘记了第二个等号,你可能会得到错误的代码。但是还有另一个原因也与C#相匹配:可读性。

举个简单的例子:

if(someVariableThatShouldBeChecked != null
   && anotherOne != null
   && justAnotherCheckThatIsNeededForTestingNullity != null
   && allTheseChecksAreReallyBoring != null
   && thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded != null)
{
    // ToDo: Everything is checked, do something...
}

如果您只是将所有 null 单词交换到开头,您可以更轻松地查看所有检查:

if(null != someVariableThatShouldBeChecked
   && null != anotherOne
   && null != justAnotherCheckThatIsNeededForTestingNullity
   && null != allTheseChecksAreReallyBoring
   && null != thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded)
{
    // ToDo: Everything is checked, do something...
}

所以这个例子可能是一个不好的例子(参考编码指南),但想想你快速滚动一个完整的代码文件。通过简单地看到模式

if(null ...

你马上知道接下来会发生什么。

如果是相反的方式,你总是必须扫描到行的末尾才能看到无效检查,只是让你绊倒了一秒钟,找出什么样的检查是在那里。因此,语法突出显示可能会对您有所帮助,但是当这些关键字位于行的末尾而不是前面时,您总是会变慢。

答案 4 :(得分:4)

在早些时候,人们会忘记'!' (或更多的'='表示相等,更难以发现)并进行分配而不是比较。将null置于前面可以消除bug的可能性,因为null不是l值(I.E.它不能分配给它)。

现在大多数现代编译器都会在条件中执行赋值时发出警告,而C#实际上会出错。大多数人只是坚持使用var == null方案,因为对某些人来说它更容易阅读。

答案 5 :(得分:4)

我没有看到遵循这一惯例的任何优势。在C中,布尔类型不存在,写入

很有用
if( 5 == variable)

而不是

if (variable == 5)

因为如果你忘记了其中一个等号,你最终会得到

if (variable = 5)

将5赋值给变量并始终求值为true。但在Java中,布尔值是布尔值。有了!=,根本就没有理由。

但是,一个好的建议就是写

if (CONSTANT.equals(myString))

而不是

if (myString.equals(CONSTANT))

因为它有助于避免NullPointerExceptions。

我的建议是要求对该规则进行辩护。如果没有,为什么要遵循它?它没有帮助可读性

答案 6 :(得分:0)

对我而言,你总是喜欢哪种风格

@Shy - 然后再次如果你混淆了操作符然后你应该想要得到一个编译错误,或者你将运行带有错误的代码 - 这个错误会在以后出现,并且会因为它产生意外行为而咬你/ p>

答案 7 :(得分:0)

正如许多人指出的那样,它主要是用旧的C代码来识别编译错误,因为编译器认为它是合法的

像java,go这样的新编程语言足够聪明,可以捕获此类编译错误

一个人不应该像代码中的条件那样使用“ null!= variable”,因为它非常不可读

答案 8 :(得分:-4)

还有一件事......如果你要将变量与常量(例如整数或字符串)进行比较,那么将常量放在左边是很好的做法,因为你永远不会遇到NullPointerExceptions:

int i;
if(i==1){        // Exception raised: i is not initialized. (C/C++)
  doThis();
}

,而

int i;
if(1==i){        // OK, but the condition is not met.
  doThis();
}

现在,由于默认情况下C#会对所有变量进行实例化,因此您不应该使用该语言存在该问题。