我经常在必要时执行此操作以防止空指针异常:
// 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
}
答案 0 :(得分:11)
在您提供的示例中:
if (table == null || table.Rows == null || table.Rows.Count <= 0)
{
// Do something
}
如果table.Rows
为空, ... table.Rows.Count
和tables
都不会被取消引用。
这是因为,使用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语句,那么它就不会被评估......