关于c#:是吗?

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();

如果不返回null,它会两次调用ReallyComplexFunction。(尽管这看起来是一个荒谬的实现,但是如果用一个可以为空的变量替换函数,它看起来相当合理:return a == null ? 42 : a)

如上所述,我知道在我的测试中它只被调用一次,但我的问题是,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);

不管你怎么看,ReallyCleverFunction只被调用一次。


??运算符与左手无关。首先运行左手,然后由??运算符评估其响应。

在您的代码中,ReallyCleverFunction只运行一次。


首先,答案是"是",它确实保证只评估一次,通过官方C语言规范第7.13节的推论。

第7.13节总是将a视为一个对象,因此它必须只接受函数的返回并在处理中使用它。上面写的是关于??操作员(增加重点):

? 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函数的返回值。