在 .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 中,AndAlso
和 OrElse
也是短路的。
在 javascript 中,&&
和 ||
也是短路的。
我提到 VB.NET 是为了表明 .net 丑陋的红发继子有时也有很酷的东西。
我提到了 javaScript,因为如果你正在做 Web 开发,那么你可能还会使用 javaScript。
【讨论】:
本质上,a || b
等价于a ? a : b
,a && 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
仅在x
为true
时才被评估 ... 操作x && y
被评估为(bool)x ? (bool)y : false
。换句话说,x
首先被评估并转换为类型bool
。然后,如果x
是true
,则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
并返回左侧,则它根本不计算右侧,否则调用自定义 &
运算符。所以它模仿了bool
s 的短路行为。这个的典型应用是一个扩展的bool
,它可以有第三种状态。例如,您可以实现类似于 DBBol
或 bool?
的东西。
我希望我们有 &&=
和 ||=
运算符。【参考方案4】:
是的,C# 使用逻辑短路。
请注意,尽管 C#(和其他一些 .NET 语言)以这种方式运行,但它是该语言的属性,而不是 CLR。
【讨论】:
实际上,VB.NET 在使用AndAlso
和OrElse
时的行为是这样的,在And
和Or
上使用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 中依赖 && 短路安全吗?的主要内容,如果未能解决你的问题,请参考以下文章