C#逻辑顺序和编译器行为
在C#中,(对于其他语言,可以随意回答),运行时按什么顺序评估逻辑语句?
例子:
DataTable myDt = new DataTable(); if (myDt != null && myDt.Rows.Count > 0) { //do some stuff with myDt }
运行时首先评估哪个语句-
myDt != null
或者:
myDt.Rows.Count > 0
?
是否有一段时间编译器会向后评估该语句?也许当涉及到"或者"运算符时?
& is known as a logical bitwise operator and will always evaluate all the sub-expressions
何时使用按位运算符代替"短路布尔值"的一个好例子是什么?
解决方案
回答
左边的为空,然后停止。
编辑:在vb.net中,它将同时评估这两者,并且可能会引发错误,除非我们使用AndAlso
回答
C:从左到右,如果发现不匹配(评估为假),则处理停止。
回答
我在某处听说编译器会向后工作,但是我不确定这是多么真实。
回答
vb.net
if( x isNot Nothing AndAlso x.go()) then
- 从左到右进行评估
- AndAlso运算符确保仅当左侧为TRUE时,才对右侧进行评估(非常重要,因为ifx无关x.go会崩溃)
我们可以在vb中使用And代替AndAlso。在这种情况下,左侧也将首先进行评估,但是无论结果如何,右侧都将得到评估。
最佳实践:除非我们有充分的理由不这样做,否则请始终使用AndAlso。
在后续活动中,有人问为什么或者何时将使用And而不是AndAlso(或者&而不是&&):
if ( x.init() And y.init()) then x.process(y) end y.doDance()
这是一个例子:
在这种情况下,我想同时初始化X和Y。为了使y.DoDance能够执行,必须初始化Y。但是,在init()函数中,我还执行其他一些操作,例如检查套接字是否打开,并且只有在工作正常的情况下,对于两者,我都应该继续执行x.process(y)。
回答
同样,在99%的情况下,这可能不是必需的,也不是很优雅,这就是为什么我说默认应该使用AndAlso。
if( A && B){ // do something }
谦虚这个概念指的是操作员重载。在声明中:
if(A || B){ //do something }
首先评估A,如果评估为false,则永远不会评估B。同样适用于
首先评估A,如果评估为true,则永远不会评估B。
回答
重载这个概念适用于(我认为)所有C风格语言以及许多其他语言。
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 }
回答
ZombieSheep已经死了。可能正在等待的唯一"陷阱"是,只有在使用&&运算符时,这才是正确的。使用&运算符时,每次都会对这两个表达式进行求值,而不管一个或者两个求值为false。
请注意,&&和&之间在计算表达式的多少方面有所不同。
&&被称为短路布尔AND,如此处其他人所述,如果可以在评估所有子表达式之前确定结果,它将尽早停止。
&被称为逻辑按位运算符,它将始终评估所有子表达式。
if (a() && b())
因此:
仅当a返回true时才调用b。
if (a() & b())
但是,这:
即使调用a的结果为false,因此无论调用b的结果如何,都将始终调用a和b。
回答
||存在相同的差异和|运营商。
某些语言在有趣的情况下会以不同的顺序执行表达式。我特别在考虑Ruby,但是我确定他们是从其他地方(可能是Perl)借来的。
puts message unless message.nil?
逻辑中的表达式将保持从左到右,但是例如:
以上将评估" message.nil?"首先,然后如果它的计算结果为false(除非与条件条件为false而不是true时执行相反,否则将执行" puts message",这会将message变量的内容打印到屏幕上)。
有时,这是一种有趣的结构化代码的方式...我个人喜欢将其用于像上面这样的非常短的1个衬里。
编辑:
unless message.nil? puts message end
回答
为了更清楚一点,以上内容与以下内容相同:
回答
What is a good example of when to use the bitwise operator instead of the "short-circuited boolean"?
是的,至少Ccompiler不会向后工作(在&&或者||中)。从左到右。
READ 0100 WRITE 0010 EXEC 0001
假设我们有标志,例如文件属性。假设我们已将READ定义为4,将WRITE定义为2,将EXEC定义为1.
flags = READ & EXEC; // value of flags is 0101
回答
每个标志都有一个设置的位,并且每个标志都是唯一的。按位运算符使我们可以组合以下标志:
The concept modesty is referring to is operator overloading. in the statement: ... A is evaluated first, if it evaluates to false, B is never evaluated. The same applies to
@shsteimer
这不是运算符重载。运算符重载是一个术语,用于让我们定义运算符的自定义行为,例如*,+,=等。
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.
这样我们就可以编写自己的" Log"类,然后执行
a() || b() // be never runs if a is true
这样做
回答
实际上称为短路评估
当我们特别想评估所有子表达式时,可以使用&,这很可能是因为它们具有所需的副作用,即使最终结果将为假,因此也不会执行if语句的then部分。
回答
请注意&和|不仅适用于按位运算,还适用于按位掩码和布尔值。它们被按位调用,但是在C#中为整数和布尔数据类型定义了它们。
当所有事情都在线时,它们从左到右执行。
当事物嵌套时,它们从内到外执行。这似乎令人困惑,因为通常"最内层"位于该行的右侧,因此似乎向后退了。
a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );
例如
- 用文字" Orion"调用GetAddress。
- 用文字" Orion"和GetAddress的结果调用" GetSummary"。
- 用字面量" 5"和结果" GetSummary"调用" Foo"。
- 将此值分配给
a
回答
事情像这样发生:
我知道这个问题已经得到解答,但是我想补充一点与该主题相关的信息。
- 由于重载是必须调用的函数,因此它打破了延迟评估机制,因此在调用该函数之前都要对这两个参数进行评估。
- 不能保证对这些参数的求值顺序,并且可以是编译器特定的。因此,对象的行为方式与问题/先前答案中列出的示例不同。
在C ++等语言中,实际上我们可以重载&&和||的行为。运算符,强烈建议我们不要这样做。这是因为当我们超载此行为时,我们最终将迫使对操作双方进行评估。这有两件事:
回答
有关更多信息,请阅读Scott Meyers的书《更有效的C ++》。干杯!
- 从左到右仍然首先适用
- 由内而外确保在调用函数之前解析所有参数
我喜欢猎户座的回应。我将添加两件事:
a = Foo(5, GetSummary("Orion", GetAddress("Orion")), GetSummary("Chris", GetAddress("Chris")));
假设我们有以下示例:
GetAddress(" Orion")
- GetSummary("猎户座",...)`
GetAddress(" Chris")
- " GetSummary(" Chris",...)`
Foo(...)
- 分配给
a
执行顺序如下:
我不能谈论C#的法律要求(尽管在撰写本文之前,我曾使用Mono测试过类似的示例),但是Java保证了此顺序。
- foo()&& bar()
- foo()和bar()
只是为了完整性(因为这也是与语言无关的线程),所以还有C和C ++之类的语言,除非有序列点,否则无法保证顺序。参考文献:1、2. 但是,在回答线程的问题时,&&
和||
是C ++中的序列点(除非重载;另请参见OJ的出色回答)。下面是一些例子:
回答
在&&
情况下,由于&&
是一个序列点,因此保证foo()可以在bar()之前运行(如果后者完全运行)。在
&`的情况下,(在C和C ++中)没有这样的保证,实际上,bar()可以在foo()之前运行,反之亦然。
" C:从左到右,如果找到匹配项(评估为真),则处理停止。"
僵尸羊是错的,没有足够的代表来拒绝投票。
问题是关于&&运算符,而不是||。操作员。
在&&的情况下,如果找到FALSE,评估将停止。
回答
对于||如果找到TRUE,则评估停止。
It was asked in a followup why or when would anyone use And instead of AndAlso (or & instead of &&): Here is an example: if ( x.init() And y.init()) then x.process(y) end y.doDance() In this case, I want to init both X and Y. Y must be initialized in order for y.DoDance to be able to execute. However, in the init() function I am doing also some extra thing like checking a socket is open, and only if that works out ok, for both, I should go ahead and do the x.process(y).
@csmba:
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
回答
我相信这很令人困惑。尽管示例可行,但这不是使用And
的典型情况(为了清楚起见,我可能会写不同的方式)。实际上,"与"(其他大多数语言中的"与")是按位与运算。我们将使用它来计算位操作,例如删除标志位或者屏蔽和测试标志:
段落数量不匹配