6

在 C# 中,是否保证表达式从左到右进行评估?

例如:

myClass = GetClass();  
if (myClass == null || myClass.Property > 0)  
    continue;

有没有不符合的语言?

4

9 回答 9

14

您实际上指的是一种称为“短路逻辑表达式”的语言功能:

这意味着:当一个逻辑表达式的结果不能再改变时,例如当很明显该表达式无论如何都会计算为“真”或“假”时,表达式的其余部分将不会被计算。

例如,C#、Java 或 JavaScript 可以做到这一点,您可以在这些语言中依赖它(回答您的问题)。

在您的情况下,如果 MyClass 不为空:

  • MyClass == null评估为假
  • 因为它是一个“或”表达式,第二部分仍然可以改变结果,所以它被评估
  • myClass.Property > 0决定最终结果

如果 MyClass 为空:

  • MyClass == null评估为真
  • 因为它是一个“或”表达式,所以后面的内容无关紧要
  • 不再进行评估,最终结果为真

有些语言不会短路逻辑表达式。经典 VB 就是一个示例,如果 MyClass 为空(在 VB 中称为“Nothing”),此处将评估“myClass.Property > 0”并产生错误。

于 2008-12-03T10:39:52.803 回答
5

C# 3.0 规范的第 7.11 节描述了短路:

操作 x || y 对应于操作 x | y,除了只有当 x 不为真时才评估 y。

所以,是的,你很好。

至于其他语言——我从不喜欢代表所有语言。在 VB.NET 中,您可以使用短路的 OrElse 和 AndAlso,但普通的 Or 和 And 没有。

于 2008-12-03T10:44:49.407 回答
2

不过要小心:

如果你有类似的东西

sprintf(buf, "%s %s", func1(&var), func2(&var));

对 var 有副作用,它没有定义(在 C 中,我不确定评估顺序是否在其他语言中定义),执行 func1() 和 func2() 的顺序(这取决于,以什么顺序(左或对)参数被放入堆栈并从那里评估。

于 2008-12-03T10:45:14.290 回答
0

评估顺序取决于运算符,在这种情况下,布尔值或 ( ||) 被定义为通常称为短路的东西,以使这样的构造工作。

于 2008-12-03T10:37:34.837 回答
0

我不确定,您真的对订单或短路评估感兴趣吗?

我不是 100% 确定,但据我所知,C# 中的评估顺序始终是相同的(我假设大多数(如果不是全部).net 语言)。短路评估的工作原理如前面的答案中所述。

但是,在 C# 中,您可以选择不使用简单的运算符(用 & 代替 &&)进行短路。通常您想要短路,但也可能是您想要执行所有评估的情况。

于 2008-12-03T10:46:09.263 回答
0

Ada、Visual Basic 和 Pascal 等语言中的和/或运算符不会短路。它们确实提供了额外的运算符来允许该功能,例如 Ada 中的“然后”和“否则”。

于 2008-12-03T10:46:40.200 回答
0

Python 有短路orand运算符。

于 2008-12-03T11:06:10.003 回答
0

在 Java 和 Haskell 中 && 和 || 短路也是如此。

有趣的是:在 Haskell 中,语言自然而然地出现了这一点(您可以定义自己的运算符来执行此操作),而在 Java 和 C# 中,它是特定于这两个运算符的。

于 2008-12-03T11:13:00.100 回答
0

实际上短路是一部分,但您还需要知道语言是否保证对它们进行从左到右的评估。例如 C (ANSI, ISO, C99) 不保证从左到右的评估。在示例代码中,可以在检查 NULL 之前检查 Property 的值,或者同时执行这两项操作……大多数编译器都没有,但是没有什么能阻止它这样做并完全符合规范。它甚至告诉你不要因此编写这样的代码。

于 2010-04-13T05:27:23.367 回答