Why does one often see “null != variable” instead of “variable != null” in C#?
在c#中,陈述条件的顺序的执行速度是否有差异?
1 2 | if (null != variable) ... if (variable != null) ... |
从最近开始,我经常看到第一个,自从我习惯了第二个以来,它引起了我的注意。
如果没有区别,第一个的优势是什么?
这是C语言的保留。在C语言中,如果您使用错误的编译器或没有将警告提高到足够高的水平,则将在没有警告的情况下进行编译(实际上是合法代码):
1 2 | // Probably wrong if (x = 5) |
当你实际上可能意味着
1 | if (x == 5) |
您可以通过以下方法在C中解决此问题:
1 | if (5 == x) |
此处输入错误将导致代码无效。
现在,在C#中,这真是个难题。除非要比较两个布尔值(IME很少见),否则您可以编写更具可读性的代码,因为" if"语句要求以布尔值开头,并且"
我建议,如果您在同事的代码中看到了这一点,请以现代语言的方式对其进行教育,并建议他们将来编写更自然的形式。
有充分的理由先使用null:
如果您的
首先使用
(我听说您最终会习惯于阅读用这种方式编写的代码-我只是还没有经历过这种转换)。
这是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 } } |
就像大家已经指出的那样,它或多或少地来自C语言,如果您不小心忘记了第二个等号,则可能会得到错误的代码。但是还有另一个与C#相匹配的原因:可读性。
仅举一个简单的例子:
1 2 3 4 5 6 7 8 | if(someVariableThatShouldBeChecked != null && anotherOne != null && justAnotherCheckThatIsNeededForTestingNullity != null && allTheseChecksAreReallyBoring != null && thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded != null) { // ToDo: Everything is checked, do something... } |
如果您只是将所有空词交换到开头,则可以更轻松地发现所有检查:
1 2 3 4 5 6 7 8 | if(null != someVariableThatShouldBeChecked && null != anotherOne && null != justAnotherCheckThatIsNeededForTestingNullity && null != allTheseChecksAreReallyBoring && null != thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded) { // ToDo: Everything is checked, do something... } |
因此,此示例可能是一个不好的示例(请参阅编码指南),但请考虑一下您快速滚动浏览完整的代码文件。通过简单地看到模式
1 | if(null ... |
您立即知道接下来会发生什么。
如果相反,您总是必须扫描到该行的末尾以查看无效检查,只是让您绊倒一秒钟以找出进行哪种检查。因此,语法突出显示也许可以为您提供帮助,但是当这些关键字位于行尾而不是行尾时,您总是会变慢。
我猜这是一个切换语言的C程序员。
在C中,您可以编写以下内容:
1 2 3 4 5 | int i = 0; if (i = 1) { ... } |
注意那里使用了一个等号,这意味着代码将给变量i分配1,然后返回1(一个赋值是一个表达式),并在if语句中使用1,这将被视为true。换句话说,以上是一个错误。
但是,在C#中,这是不可能的。两者之间确实没有区别。
遵循此约定我看不出任何优势。在不存在布尔类型的C语言中,编写
1 | if( 5 == variable) |
而不是
1 | if (variable == 5) |
因为如果忘记其中一个等号,您最终会得到
1 | if (variable = 5) |
将5赋给变量,并始终求值为true。但是在Java中,布尔值是布尔值。并且使用!=根本没有任何理由。
不过,一个好的建议是写
1 | if (CONSTANT.equals(myString)) |
而不是
1 | if (myString.equals(CONSTANT)) |
因为它有助于避免NullPointerExceptions。
我的建议是要求对规则进行辩护。如果没有,为什么要遵循?它不利于可读性
在早期,人们会忘记"!" (或额外的'='代表相等性,这很难发现),然后分配而不是进行比较。将null放在前面可以消除该错误的可能性,因为null不是l值(即,它不能分配给它)。
在当今有条件的情况下执行赋值操作时,大多数现代编译器都会发出警告,而C#实际上会给出错误。大多数人只是坚持使用var == null方案,因为它对某些人来说更容易阅读。
许多人指出,它主要是用旧的C代码来识别编译错误,因为编译器认为它是合法的
像Java这样的新编程语言go足够聪明,可以捕获此类编译错误
人们不应该像代码中的条件那样使用" null!= variable",因为它非常不可读
对我来说,一直是您喜欢哪种风格
@Shy-再一次,如果您使运算符感到困惑,那么您应该想得到一个编译错误,否则您将在运行代码时遇到一个错误-一个错误又回来了,并在以后咬住了您,因为它产生了意外的行为
还有一件事...如果将变量与常量(例如整数或字符串)进行比较,则将常量放在左侧是一种好习惯,因为您永远不会遇到NullPointerExceptions:
1 2 3 4 | int i; if(i==1){ // Exception raised: i is not initialized. (C/C++) doThis(); } |
而
1 2 3 4 | int i; if(1==i){ // OK, but the condition is not met. doThis(); } |
现在,由于默认情况下C#实例化了所有变量,因此您不应该使用该语言来解决该问题。