C# 逻辑顺序和编译器行为
在 C# 中(也可以随意回答其他语言),运行时计算逻辑语句的顺序是什么?
示例:
DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
//do some stuff with myDt
}
运行时首先评估哪个语句 -
myDt != null
或:
myDt.Rows.Count > 0
?
编译器是否会向后评估该语句? 也许当涉及“OR”运算符时?
& 被称为逻辑按位运算符,并且将始终计算所有子表达式
何时使用按位运算符而不是“短路布尔值”的一个很好的例子是什么?
In C#, (and feel free to answer for other languages), what order does the runtime evaluate a logic statement?
Example:
DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
//do some stuff with myDt
}
Which statement does the runtime evaluate first -
myDt != null
or:
myDt.Rows.Count > 0
?
Is there a time when the compiler would ever evaluate the statement backwards? Perhaps when an "OR" operator is involved?
& is known as a logical bitwise operator and will always evaluate all the sub-expressions
What is a good example of when to use the bitwise operator instead of the "short-circuited boolean"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
当一切都在线时,它们将从左到右执行。
当事物嵌套时,它们是从内到外执行的。 这可能看起来很令人困惑,因为通常“最里面”的内容位于该行的右侧,因此看起来像是在向后移动......
例如,
事情发生如下:
GetAddress
"Orion"
"Orion"
调用GetSummary
以及GetAddress
调用Foo< /code> 带有文字
5
和GetSummary
的结果a
When things are all in-line, they're executed left-to-right.
When things are nested, they're executed inner-to-outer. This may seem confusing as usually what's "innermost" is on the right-hand side of the line, so it seems like it's going backwards...
For example
Things happen like this:
GetAddress
with the literal"Orion"
GetSummary
with the literal"Orion"
and the result ofGetAddress
Foo
with the literal5
and the result ofGetSummary
a
我意识到这个问题已经得到解答,但我想补充一些与该主题相关的信息。
在 C++ 等语言中,您实际上可以重载 && 的行为。 和 || 运营商,强烈建议您不要这样做。 这是因为当您重载此行为时,您最终会强制对操作的两侧进行评估。 这做了两件事:
有关详细信息,请阅读 Scott Meyers 的书更高效的 C++。 干杯!
I realise this question has already been answered, but I'd like to throw in another bit of information which is related to the topic.
In languages, like C++, where you can actually overload the behaviour of the && and || operators, it is highly recommended that you do not do this. This is because when you overload this behaviour, you end up forcing the evaluation of both sides of the operation. This does two things:
For more info, have a read of Scott Meyers' book, More Effective C++. Cheers!
“C#:从左到右,如果找到匹配项(评估结果为 true),则处理停止。”
僵尸羊错了。
问题是关于 && 运算符,而不是 || 操作员。
在 && 的情况下 如果发现 FALSE,评估将停止。
在 || 的情况下 如果找到 TRUE,则评估停止。
"C# : Left to right, and processing stops if a match (evaluates to true) is found."
Zombie sheep is wrong.
The question is about the && operator, not the || operator.
In the case of && evaluation will stop if a FALSE is found.
In the case of || evaluation stops if a TRUE is found.
C#:从左到右,如果发现不匹配(计算结果为 false),则处理停止。
C# : Left to right, and processing stops if a non-match (evaluates to false) is found.
vb.net
你可以在 vb 中使用 And 而不是 AndAlso。 在这种情况下,左侧也会首先被评估,但无论结果如何,右侧都会被评估。
最佳实践:始终使用 AndAlso,除非您有充分的理由不这样做。
在后续中有人问为什么或何时有人会使用 And 而不是 AndAlso(或 & 而不是 &&):
下面是一个示例:
在本例中,我想要初始化 X 和 Y。必须初始化 Y 才能使 y.DoDance 能够执行。 但是,在 init() 函数中,我还做了一些额外的事情,例如检查套接字是否打开,并且只有当效果正常时,对于两者,我应该继续执行 x.process (y)。
同样,在 99% 的情况下这可能是不需要的,而且也不优雅,这就是为什么我说默认应该使用 AndAlso。
vb.net
You may use And instead ofAndAlso in vb. in which case the left side gets evaluated first as well, but the right side will get evaluated regardless of result.
Best Practice: Always use AndAlso, unless you have a very good reason why not to.
It was asked in a followup why or when would anyone use And instead of AndAlso (or & instead of &&):
Here is an example:
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).
Again, this is probably not needed and not elegant in 99% of the cases, that is why I said that the default should be to use AndAlso.
@shsteimer
That's not 运算符重载。 运算符重载是一个术语,用于让您定义运算符的自定义行为,例如 *、+、= 等。
这将让您编写自己的“Log”类,然后执行
此操作
实际上称为 短路评估
@shsteimer
That's not operator overloading. Operator overloading is the term given for letting you define custom behaviour for operators, such as *, +, = and so on.
This would let you write your own 'Log' class, and then do
Doing this
is actually called Short Circuit Evaluation
请注意,&& 之间存在差异。 和& 关于评估您的表达的程度。
&& 被称为短路布尔 AND,并且正如其他人在此指出的那样,如果可以在计算所有子表达式之前确定结果,则将提前停止。
& 被称为逻辑按位运算符,并且将始终计算所有子表达式。
因此:
仅当 a 返回 true 时才会调用 b。
但是,这:
将始终调用 a 和 b,即使调用 a 的结果为 false,因此已知为 false,无论调用 b 的结果如何。
|| 也存在同样的差异 和 | 运营商。
Note that there is a difference between && and & regarding how much of your expression is evaluated.
&& is known as a short-circuited boolean AND, and will, as noted by others here, stop early if the result can be determined before all the sub-expressions are evaluated.
& is known as a logical bitwise operator and will always evaluate all the sub-expressions.
As such:
Will only call b if a returns true.
however, this:
Will always call both a and b, even though the result of calling a is false and thus known to be false regardless of the result of calling b.
This same difference exists for the || and | operators.
ZombieSheep 完全正确。 唯一可能等待的“问题”是,只有当您使用 && 时,这才是正确的。 操作员。 当使用 & 运算符,每次都会计算两个表达式,无论一个或两个表达式的计算结果是否为 false。
ZombieSheep is dead-on. The only "gotcha" that might be waiting is that this is only true if you are using the && operator. When using the & operator, both expressions will be evaluated every time, regardless if one or both evaluate to false.
左边的,如果为空则停止。
编辑:在 vb.net 中,它将评估两者并可能引发错误,除非您使用 AndAlso
The left one, then stops if it is null.
Edit: In vb.net it will evaluate both and possibly throw an error, unless you use AndAlso
谦虚所指的概念是运算符重载。 在语句中:
首先评估 A,如果评估为 false,则永远不会评估 B。 这同样适用于
首先评估 A,如果评估为 true,则永远不会评估 B。
这个概念,重载,适用于(我认为)所有 C 风格语言,以及许多其他语言。
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
A is evaluated first, if it evaluates to true, B is never evaluated.
This concept, overloading, applies to (i think) all of the C style languages, and many others as well.
有些语言有一些有趣的情况,其中表达式以不同的顺序执行。 我特别想到 Ruby,但我确信他们从其他地方(可能是 Perl)借用了它。
逻辑中的表达式将保持从左到右,但例如:
上面将计算“message.nil?” 首先,如果它的计算结果为 false(除非它在条件为 false 而不是 true 时执行),则将执行“puts message”,它将 message 变量的内容打印到屏幕上。
有时,这是一种构建代码的有趣方式...我个人喜欢将它用于像上面这样的非常短的 1 行。
编辑:
为了更清楚一点,上面的内容与:
Some languages have interesting situations where expressions are executed in a different order. I am specifically thinking of Ruby, but I'm sure they borrowed it from elsewhere (probably Perl).
The expressions in the logic will stay left to right, but for example:
The above will evaluate "message.nil?" first, then if it evaluates to false (unless is like if except it executes when the condition is false instead of true), "puts message" will execute, which prints the contents of the message variable to the screen.
It's kind of an interesting way to structure your code sometimes... I personally like to use it for very short 1 liners like the above.
Edit:
To make it a little clearer, the above is the same as:
不,至少 C# 编译器不会向后工作(在 && 或 || 中)。 它是从左到右。
Nopes, at least the C# compiler doesn't work backwards (in either && or ||). It's left to right.
我喜欢猎户座的回应。 我将添加两件事:
假设我们有以下示例:
这是执行顺序:
GetAddress (“猎户座”)
GetSummary(“猎户座”,...)
GetAddress(“克里斯”)
GetSummary(“克里斯”,.. .)
Foo(...)
a
我无法谈论 C# 的法律要求(尽管在编写之前我确实使用 Mono 测试了类似的示例)这篇文章),但这个顺序在 Java 中是有保证的。
为了完整性(因为这也是一个与语言无关的线程),有一些语言,如 C 和 C++,除非存在序列点,否则无法保证顺序。 参考文献:1、2。 然而,在回答线程的问题时,
&&
和||
是 C++ 中的序列点(除非重载;另请参阅 OJ 的优秀答案)。 一些例子:foo() && bar()
foo() & bar()
在
&&
情况下,保证foo()
在bar()
之前运行(如果后者完全运行),因为&&
是一个序列点。 在&
情况下,没有做出这样的保证(在 C 和 C++ 中),并且实际上bar()
可以在foo()
之前运行, 或相反亦然。I like Orion's responses. I'll add two things:
Say we have the following example:
Here's the order of execution:
GetAddress("Orion")
GetSummary("Orion", ...)
GetAddress("Chris")
GetSummary("Chris", ...)
Foo(...)
a
I can't speak about C#'s legal requirements (although I did test a similar example using Mono before writing this post), but this order is guaranteed in Java.
And just for completeness (since this is a language-agnostic thread as well), there are languages like C and C++, where the order is not guaranteed unless there is a sequence point. References: 1, 2. In answering the thread's question, however,
&&
and||
are sequence points in C++ (unless overloaded; also see OJ's excellent answer). So some examples:foo() && bar()
foo() & bar()
In the
&&
case,foo()
is guaranteed to run beforebar()
(if the latter is run at all), since&&
is a sequence point. In the&
case, no such guarantee is made (in C and C++), and indeedbar()
can run beforefoo()
, or vice versa.假设您有标志,例如文件属性。 假设您将 READ 定义为 4,将 WRITE 定义为 2,将 EXEC 定义为 1。在二进制中,即:
每个标志都设置了一位,并且每一位都是唯一的。 按位运算符可让您组合这些标志:
Suppose you have flags, say for file attributes. Suppose you've defined READ as 4, WRITE as 2, and EXEC as 1. In binary, that's:
Each flag has one bit set, and each one is unique. The bitwise operators let you combine these flags:
我听说过编译器向后工作,但我不确定这有多真实。
I have heard somewhere that compilers work backwards, but I am unsure how true this is.
您使用 & 当您特别想要计算所有子表达式时,很可能是因为它们具有您想要的副作用,即使最终结果将是 false 并因此不执行您的 then > if 语句的一部分。
请注意 & 和 | 适用于按位掩码和布尔值,而不仅仅是按位运算。 它们被称为按位,但它们是为 C# 中的整数和布尔数据类型定义的。
You use & when you specifically want to evaluate all the sub-expressions, most likely because they have side-effects you want, even though the final result will be false and thus not execute your then part of your if-statement.
Note that & and | operates for both bitwise masks and boolean values and is not just for bitwise operations. They're called bitwise, but they are defined for both integers and boolean data types in C#.
@csmba:
我相信这相当令人困惑。 尽管您的示例有效,但它不是使用
And
的典型情况(我可能会以不同的方式编写它以使其更清晰)。And
(大多数其他语言中的&
)实际上是按位与运算。 您可以使用它来计算位操作,例如删除标志位或屏蔽和测试标志:@csmba:
I believe this is rather confusing. Although your example works, it's not the typical case for using
And
(and I would probably write this differently to make it clearer).And
(&
in most other languages) is actually the bitwise-and operation. You would use it to calculate bit operations, for example deleting a flag bit or masking and testing flags:D 编程语言确实执行从左到右短路求值 和 不允许 重载
&&
和 '||' 运算符。The D programming language Does do left-to-right evaluation with short circuiting and doesn't allow overloading of the
&&
and '||' operators.