在C#中,(可以随意回答其他语言),运行时评估逻辑语句的顺序是什么?
示例:
DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
//do some stuff with myDt
}
运行时首先评估哪个语句 -
myDt != null
或:
myDt.Rows.Count > 0
是否有时候编译器会向后评估语句?也许当涉及“OR”运算符时?
&安培;被称为逻辑按位运算符,并将始终评估所有子表达式
什么时候使用按位运算符而不是“短路布尔值”的好例子?
答案 0 :(得分:16)
C#:从左到右,如果找到不匹配(评估为false),则处理停止。
答案 1 :(得分:9)
“C#:从左到右,如果找到匹配(评估为真),则处理停止。”
僵尸羊是错的,没有足够的代表向下投票。
问题在于&&运算符,而不是||操作
在&&如果找到FALSE,评估将停止。
在||的情况下如果找到TRUE,评估将停止。
答案 2 :(得分:8)
我意识到这个问题已经得到解答,但我想提出与该主题相关的其他一些信息。
在C ++这样的语言中,你实际上可以超载&&amp ;;的行为。和||运营商,强烈建议您不要这样做。这是因为当您重载此行为时,最终会强制对操作的两端进行评估。这有两件事:
欲了解更多信息,请阅读Scott Meyers的书籍More Effective C++。干杯!
答案 3 :(得分:6)
<强> vb.net 强>
if( x isNot Nothing AndAlso x.go()) then
你可以在vb中使用和而不是和Also。在这种情况下,左侧也会先被评估,但无论结果如何,都会评估右侧。
最佳实践:始终使用AndAlso,除非你有充分的理由不去。
有人在跟进中询问为什么或何时使用And而不是AndAlso(或&amp;而不是&amp;&amp;): 这是一个例子:
if ( x.init() And y.init()) then
x.process(y)
end
y.doDance()
在这种情况下,我想初始化X和Y.必须初始化Y才能使y.DoDance能够执行。但是,在init()函数中我还做了一些额外的事情,比如检查一个套接字是否打开,只有当它运行正常时,对于两者,我应该继续执行x.process (y)的
同样,这可能不是必需的,并且在99%的情况下都不优雅,这就是为什么我说默认应该是使用 AndAlso 。
答案 4 :(得分:5)
@shsteimer
概念谦虚是指运营商重载。在声明中: ... 首先评估A,如果评估为false,则从不评估B.这同样适用于
这不是运算符重载。运算符重载是允许您为运算符定义自定义行为的术语,例如*,+,=等。
这可以让你编写自己的“Log”类,然后执行
a = new Log(); // Log class overloads the + operator
a + "some string"; // Call the overloaded method - otherwise this wouldn't work because you can't normally add strings to objects.
这样做
a() || b() // be never runs if a is true
答案 5 :(得分:4)
ZombieSheep已经死了。可能正在等待的唯一“问题”是,只有在使用&amp;&amp;和运营商。当使用&amp;运算符,每次都会计算两个表达式,无论其中一个或两个都是否为false。
if (amHungry & whiteCastleIsNearby)
{
// The code will check if White Castle is nearby
// even when I am not hungry
}
if (amHungry && whiteCastleIsNearby)
{
// The code will only check if White Castle is nearby
// when I am hungry
}
答案 6 :(得分:4)
请注意&amp;&amp;和和&amp;关于你的表达有多少被评估。
&安培;&安培;被称为短路布尔AND,并且如其他人所指出的那样,如果可以在评估所有子表达式之前确定结果,则会提前停止。
&安培;被称为逻辑按位运算符,将始终评估所有子表达式。
因此:
if (a() && b())
如果 a 返回 true ,则只会调用 b 。
但是,这个:
if (a() & b())
将始终同时调用 a 和 b ,即使调用 a 的结果为false,因此已知 false ,无论调用 b 的结果如何。
||存在同样的差异和|运算符。
答案 7 :(得分:4)
某些语言有一些有趣的情况,其中表达式以不同的顺序执行。我特别想到Ruby,但我确信他们是从其他地方借来的(可能是Perl)。
逻辑中的表达式将保持从左到右,但例如:
puts message unless message.nil?
以上将评估“message.nil?”首先,如果它的计算结果为false(除非是在条件为false而不是true时执行除外),“puts messages”将执行,它将消息变量的内容输出到屏幕。
这有时是一种有趣的构建代码的方式......我个人喜欢将它用于非常短的1个衬里,如上所述。
编辑:
为了使它更清晰,以上内容与:
相同unless message.nil?
puts message
end
答案 8 :(得分:2)
概念谦虚是指运营商重载。在声明中:
if( A && B){
// do something
}
首先评估A,如果评估为false,则永远不评估B.这同样适用于
if(A || B){
//do something
}
首先评估A,如果评估为真,则永远不评估B.
这个概念,重载,适用于(我认为)所有C风格的语言,以及许多其他语言。
答案 9 :(得分:2)
左边的一个,如果为空则停止。
编辑:在vb.net中,它将评估两者并可能抛出错误,除非您使用AndAlso
答案 10 :(得分:1)
什么时候使用按位运算符而不是“短路布尔值”的好例子?
假设您有标记,例如文件属性。假设您已将READ定义为4,将WRITE定义为2,将EXEC定义为1.在二进制中,即:
READ 0100
WRITE 0010
EXEC 0001
每个标志都有一个位设置,每个标志都是唯一的。按位运算符允许您组合这些标志:
flags = READ & EXEC; // value of flags is 0101
答案 11 :(得分:1)
我喜欢猎户座的回应。我将添加两件事:
假设我们有以下示例:
a = Foo(5, GetSummary("Orion", GetAddress("Orion")),
GetSummary("Chris", GetAddress("Chris")));
以下是执行顺序:
GetAddress("Orion")
GetSummary("Orion", ...)
GetAddress("Chris")
GetSummary("Chris", ...)
Foo(...)
a
我不能谈论C#的法律要求(虽然我在写这篇文章之前使用Mono测试了一个类似的例子),但这个顺序在Java中是有保证的。
只是为了完整性(因为这是一个与语言无关的线程),还有像C和C ++这样的语言,除非有序列点,否则无法保证顺序。参考文献:1,2。然而,在回答线程的问题时,&&
和||
是C ++中的序列点(除非过载;也请参阅OJ的优秀答案)。一些例子:
foo() && bar()
foo() & bar()
在&&
案例中,foo()
保证在bar()
之前运行(如果后者全部运行),因为&&
是一个序列点。在&
的情况下,没有做出这样的保证(在C和C ++中),确实bar()
可以在foo()
之前运行,反之亦然。
答案 12 :(得分:1)
当事情全部符合要求时,它们会从左到右执行。
当事物嵌套时,它们是从内到外执行的。这可能看起来令人困惑,因为通常什么是“最里面的”在线的右侧,所以看起来它正在倒退......
例如
a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );
事情就是这样:
GetAddress
"Orion"
GetSummary
和"Orion"
的结果GetAddress
Foo
和5
的结果GetSummary
a
答案 13 :(得分:1)
Nopes,至少C#编译器不能向后工作(在&amp;&amp;或||中)。它是从左到右。
答案 14 :(得分:0)
你使用&amp;当你特别想要评估所有子表达式时,很可能是因为它们有你想要的副作用,即使最终结果是 false 因此也不会执行然后部分 if -statement。
请注意&amp;和|对按位掩码和布尔值进行操作,不仅适用于按位运算。它们按位称为,但它们是在C#中为整数和布尔数据类型定义的。
答案 15 :(得分:0)
我听说编译器在某处工作,但我不确定这是多么真实。
答案 16 :(得分:0)
有人在跟进中询问为什么或何时使用And而不是AndAlso(或者&amp;而不是&amp;&amp;):这是一个例子:
if ( x.init() And y.init()) then x.process(y) end y.doDance()
在这种情况下,我想初始化X和Y.必须初始化Y才能使y.DoDance能够执行。但是,在init()函数中我还做了一些额外的事情,比如检查一个套接字是否打开,只有当它运行正常时,对于两者,我应该继续执行x.process(y)。
我认为这很令人困惑。尽管您的示例有效,但这并不是使用And
的典型情况(我可能会以不同的方式编写它以使其更清晰)。 And
(大多数其他语言中的&
)实际上是按位和操作。您可以使用它来计算位操作,例如删除标志位或屏蔽和测试标志:
Dim x As Formatting = Formatting.Bold Or Formatting.Italic
If (x And Formatting.Italic) = Formatting.Italic Then
MsgBox("The text will be set in italic.")
End If
答案 17 :(得分:0)