在 .NET 中依赖 && 短路安全吗?

Posted

技术标签:

【中文标题】在 .NET 中依赖 && 短路安全吗?【英文标题】:Is relying on && short-circuiting safe in .NET? 【发布时间】:2011-06-16 18:38:39 【问题描述】:

假设 myObj 为空。写这个安全吗?

if(myObj != null && myObj.SomeString != null)

我知道有些语言不会执行第二个表达式,因为 && 在第二部分执行之前计算为 false。

【问题讨论】:

【参考方案1】:

在 C# 中,&&|| 是短路的,这意味着评估第一个条件,如果确定答案,则忽略其余条件。

在 VB.NET 中,AndAlsoOrElse 也是短路的。

javascript 中,&&|| 也是短路的。

我提到 VB.NET 是为了表明 .net 丑陋的红发继子有时也有很酷的东西。

我提到了 javaScript,因为如果你正在做 Web 开发,那么你可能还会使用 javaScript。

【讨论】:

本质上,a || b 等价于a ? a : ba && b 等价于a ? b : a,只是a 只计算一次。这在 JavaScript 中更为明显,可以使用任意类型的操作数。其他语言(例如 C)不遵循此原则 - 它们接受非布尔类型的操作数,但始终返回布尔值。【参考方案2】:

我知道我迟到了,但在 C# 6.0 中你也可以这样做:

if(myObj?.SomeString != null)

和上面的一样。

另见: What does question mark and dot operator ?. mean in C# 6.0?

【讨论】:

Answer 不回答问题,是对语法糖的建议,应该是评论。 @BillyBob OPs 原始问题的答案是肯定的,这里的所有其他答案已经很好地确立了这一点。这更有助于回答“提供的示例代码是否需要短路”【参考方案3】:

是的。在 C# 中,&&|| 是短路的,因此只有在左侧尚未确定结果时才评估右侧。另一方面,运算符 &| 不会短路,并且始终评估双方。

规范说:

&&|| 运算符称为条件逻辑运算符。它们也被称为“短路”逻辑运算符。 ... 操作 x && y 对应于操作 x & y,除了 y 仅在 xtrue 时才被评估 ... 操作x && y 被评估为(bool)x ? (bool)y : false。换句话说,x 首先被评估并转换为类型bool。然后,如果xtrue,则y 被求值并转换为bool 类型,这就是运算的结果。否则,运算结果为false

(C# 语言规范版本 4.0 - 7.12 条件逻辑运算符)

&&|| 的一个有趣的特性是,即使它们不是在布尔值上操作,它们也会短路,而是在用户重载运算符 &| 以及 @987654345 的类型@ 和 false 运算符。

操作x && y 被评估为T.false((T)x) ? (T)x : T.&((T)x, y),其中 T.false((T)x) 是对T 中声明的operator false 的调用,T.&((T)x, y) 是对选定operator & 的调用。此外,值 (T)x 只能计算一次。

换句话说,x 首先被计算并转换为T 类型,然后在结果上调用operator false 以确定x 是否肯定是false。 那么,如果x 肯定是false,那么运算的结果就是之前为x 计算的值转换为T 类型。 否则,将评估 y,并在先前为 x 计算的值转换为 T 和为 y 计算的值上调用选定的运算符 & 以生成操作结果。

(C# 语言规范版本 4.0 - 7.12.2 用户定义的条件逻辑运算符)

【讨论】:

最后一段有点有趣了……让我头疼。 :) 看起来很复杂,其实没那么难。如果左侧的 false 运算符返回 true 并返回左侧,则它根本不计算右侧,否则调用自定义 & 运算符。所以它模仿了bools 的短路行为。这个的典型应用是一个扩展的bool,它可以有第三种状态。例如,您可以实现类似于 DBBolbool? 的东西。 我希望我们有 &&=||= 运算符。【参考方案4】:

是的,C# 使用逻辑短路。

请注意,尽管 C#(和其他一些 .NET 语言)以这种方式运行,但它是该语言的属性,而不是 CLR。​​

【讨论】:

实际上,VB.NET 在使用AndAlsoOrElse 时的行为是这样的,在AndOr 上使用not,这可能是90% 的人们总是使用。 还需要注意的是,这不仅是一个实现细节(可以随时更改),而且是 C# 规范的一部分(在这方面不会更改)。【参考方案5】:

一个例子是

if(strString != null && strString.Length > 0)

如果双方都执行,此行将导致空异常。

有趣的旁注。上面的例子比 IsNullorEmpty 方法快很多。

【讨论】:

【参考方案6】:

是的,C# 和大多数语言从左到右计算 if 语句。

顺便说一句,VB6 会计算整个事情,如果它为空则抛出异常......

【讨论】:

这……不是完全错误,而是在很多层面上都具有误导性。 (1) 花括号语言只是执行此操作的语言的一小部分。 (2) 在解析之前反转输入是疯狂的,所以几乎没有语言会这样做。 (3) 不管怎么解析,短代码化都是运行时语义。 (4) 请参阅 harpo 关于 VB 的回答的评论 - And 不是短期课程,但 & 也不是。 (也许 2+3 是因为您将解析与运行时发生的事情混淆了......)【参考方案7】:

您的代码是安全的 - && 和 ||都是短路的。您可以使用非短路运算符 & 或 |,它们会评估两端,但我在很多生产代码中真的看不到这一点。

【讨论】:

【参考方案8】:

当然,它在 C# 上是安全的,如果第一个操作数为 false,则永远不会计算第二个操作数。

【讨论】:

如果你是“美丽的人”之一,也许有人会为你的答案投票。 你的答案是正确的,但没有CodesInChaos那么详细【参考方案9】:

绝对安全。 C# 就是其中一种语言。

【讨论】:

这里使用短路评估的语言之一 @Adam,问题是“我知道一些语言......” @Ilya Kogan:我想这意味着我应该更仔细地阅读这个问题;)

以上是关于在 .NET 中依赖 && 短路安全吗?的主要内容,如果未能解决你的问题,请参考以下文章

003客户端负载均衡Ribbon & 短路器Hystrix

最短路 spfa 算法 && 链式前向星存图

解读ASP.NET 5 & MVC6系列:依赖注入

POJ-2253 Frogger---最短路变形&&最大边的最小值

Java中逻辑&和短路&&,逻辑|和短路||的区别

使用 && 进行单线短路评估 ||在 JavaScript 中