IF语句中的运营商顺序

时间:2010-10-06 23:42:10

标签: c# if-statement nullpointerexception logical-operators

我经常在必要时执行此操作以防止空指针异常

// Example #1
if (cats != null && cats.Count > 0)
{
  // Do something
}

在#1中,我总是假设cats != null需要先行,因为操作顺序从左到右进行评估。

然而,示例#1不同,现在我想做一些事情,如果对象是null或者Count是零,那么我正在使用逻辑OR而不是AND:

// Example #2
if (table == null || table.Rows == null || table.Rows.Count <= 0)
{
  // Do something
}

逻辑比较的顺序是否重要?或者我也可以颠倒顺序并获得相同的结果,例如在示例#3中

// Example #3
if (table.Rows.Count <= 0 || table.Rows == null || table == null)
{
  // Do something
}

(顺便说一句,我知道我可以像下面那样重写#2,但我觉得它很乱,而且我仍然对OR运算符感到好奇)

// Example #4
if (!(table != null && table.Rows != null && table.Rows.Count > 0))
{
  // Do something
}

6 个答案:

答案 0 :(得分:11)

在您提供的示例中:

if (table == null || table.Rows == null || table.Rows.Count <= 0)
{
  // Do something
}
如果table.Rows为空,

... table.Rows.Counttables都不会被取消引用。

这是因为,使用C#逻辑运算符,操作顺序很重要。 C#逻辑运算符为short-circuiting - 它们从左到右进行求值,如果任何结果导致表达式的其余部分没有实际意义,则不会对表达式的其余部分进行求值。

考虑以下代码:

bool A()
{
    return false;
}

bool B()
{
    return true;
}

//...

if (A() && B())
{
    // do something
}

如果AND子句为true,则所有元素都必须为true。但是,A()返回false,运行时(或者可能是优化步骤中的编译器,但不要担心...)根本不会评估B()

OR(||)表达式也是如此。如果子句中的任何元素为true,则从左到右进行求值,则不会执行该子句的其余部分。

答案 1 :(得分:2)

是的,两种情况都会发生短路,唯一的区别是&amp;&amp;如果LHS为假(因为整体表达式必须为假),则在||时停止如果LHS为真,则停止(因为整体表达式必须为真)。

你问题中的前两个例子是正确的,如果table或table.Rows为null,第三个将抛出异常。

答案 2 :(得分:2)

您应该注意,并非所有C#逻辑运算符都表现出短路行为(如上所示)。

您正在使用Conditional-AND运算符(&amp;&amp;)并且会发生短路。然而,AND(&amp;)运算符与没有短路的条件AND完全相同。

OR和Conditional-OR运算符也是如此。

例如:

  

//如果cats为null,无论顺序如何,都会抛出。

     

if(cats!= null&amp; cats.Count&gt; 0){}

     

//这不会。由于短路。

     

if(cats!= null&amp;&amp; cats.Count&gt; 0){}

答案 3 :(得分:0)

订单很重要。这一切都与短路有关。对于ands,第一个false命中它会停止评估,对于OR,它会在遇到true时立即停止。

它会在第一次评估后短路,这就是为什么你不会得到空指针异常。

当你考虑它时,想为每个对象插入null。

if (null== null || null.Rows == null || null.null.Count <= 0)
{
  // Do something
}

然后评估每个布尔值

if( true || null.Rows == null || null.null.Count <=0)

如果你认为这意味着停止。如果你点击“null”。声明你会崩溃。

说明崩溃的示例

if (null.null.Count <= 0 || null.Rows == null || null== null)
{
  // CRASH... Do something
}

答案 4 :(得分:0)

第一种结构与第二种结构不同。第一个是当您想要在引用为null或Count为零时不执行任何操作时使用。当它为空或计数为零时,第二种结构会 DO ...要使第二种结构与你需要写的第一种相同:

 if (table == null || table.Rows == null || table.Rows.Count <= 0 || ) 
 {}
 else
 { 
  // Do something 
 } 

顺序确实很重要,即使在你编写的第二个中,如果table在尝试计算table.Rows时为null,它也会崩溃。

答案 5 :(得分:-1)

订单无关紧要。

澄清:

您将语句放在IF语句中的顺序不会影响IF语句是否进入......以及结果。

正如另一张海报指出的那样,它会影响哪些评估,但这不会影响底线AFAIK。

编辑@JonHanna

我想我从OP的角度来看这个问题,他说他在需要时正在检查NPE的事先(参见他职位的第一行)。因此,如果他的代码不会产生运行时错误,那么顺序就意味着什么。我无法想象为什么有人会用“如果这个IF语句导致NPE”的思考过程编写IF语句,那么它就不会被评估......