Does the ?? operator guarantee only to run the left-hand argument once?
例如,给定此代码:
1 2 3 4 5 6 7 8 9 | int? ReallyComplexFunction() { return 2; // Imagine this did something that took a while } void Something() { int i = ReallyCleverFunction() ?? 42; } |
…是否保证只调用一次函数?在我的测试中,它只被调用一次,但是我看不到任何说明我可以依赖于这种情况的文档。
编辑
我可以猜到它是如何实现的,但请注意:我们是开发人员。我们不应该在猜测和假设上混日子。例如,所有未来的实现都是相同的吗?另一个平台的语言实现是否相同?这取决于语言的规范以及它提供的保证。例如,一个未来或不同的平台实现(不是一个好的实现,但它是可能的)可以在
1 | return ReallyComplexFunction() == null ? 42 : ReallyComplexFunction(); |
如果不返回
如上所述,我知道在我的测试中它只被调用一次,但我的问题是,C规范是否保证/指定只调用一次左侧?如果是,在哪里?在C语言规范中,我看不到这样的提及??运算符(我最初在这里查找查询的答案)。
你的代码
1 | int i = ReallyCleverFunction() ?? 42; |
相当于(这实际上非常接近编译器实际生成的结果):
1 2 | int? temp = ReallyCleverFunction(); int i = temp.HasValue ? temp.Value : 42; |
或者更简单地说:
1 | int i = ReallyCleverFunction().GetValueOrDefault(42); |
不管你怎么看,
在您的代码中,
首先,答案是"是",它确实保证只评估一次,通过官方C语言规范第7.13节的推论。
第7.13节总是将
? If b is a dynamic expression, the result type is dynamic. At run-time, a is first evaluated. If a is not null, a is converted to dynamic, and this becomes the result. Otherwise, b is evaluated, and this becomes the result.
? Otherwise, if A exists and is a nullable type and an implicit conversion exists from b to A0, the result type is A0. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0, and this becomes the result. Otherwise, b is evaluated and converted to type A0, and this becomes the result.
? Otherwise, if A exists and an implicit conversion exists from b to A, the result type is A. At run-time, a is first evaluated. If a is not null, a becomes the result. Otherwise, b is evaluated and converted to type A, and this becomes the result.
? Otherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. Otherwise, b is evaluated and becomes the result.
附带说明的是,问题末尾给出的链接不是C语言规范,尽管它在谷歌搜索"C语言规范"时排名第一。
它只能运行一次,因为
你行
1 | int i = ReallyCleverFunction() ?? 42; |
是一样的
1 2 3 4 5 6 7 8 | int? temp = ReallyCleverFunction(); int i; if (temp != null) { i = temp.Value; } else { i = 42; } |
编译器做这项艰苦的工作。
它被调用一次,根据文档,我认为这足以假定它只被调用一次:
It returns the left-hand operand if the operand is not null; otherwise
it returns the right operand.
?运算符
它将评估函数,然后评估
它只会被调用一次。如果reallyclever函数的值为空,则使用值42,否则使用reallyclever函数的返回值。