条件运算符的引用语义

5

我正在尝试使用条件操作符(cond ? expr1 : expr2)的结果作为左值

考虑以下示例:

class /*(1)*/ Value {
    public int MagicNumber { get; private set; } = 0;
    public void Increment() {
        /* magical code, that modifies MagicNumber */
    }
}

void Main()
{
    Value v1, v2;
    /*(2)*/ bool condition = /*...*/;
    (condition ? v1 : v2).Increment(); // (3)
}

现在,我会根据condition的值来猜测,要么v1或者v2会被增加。只要Value ((1))是类,这实际上就是这种情况。一旦我将其更改为struct,它就变成了值类型,并且第(3)行不起作用(我猜测是因为要么v1v2被复制、增加和丢弃)。到目前为止,这是有意义的。奇怪的行为开始于编译时知道(2) (condition)的情况下(例如通过定义const bool)。然后会发生一些优化,并且v1v2中的一个实际上会在原地递增。

我的问题是,在以下情况下条件运算符的正确行为应该是什么?

(condition ? v1 : v2).Increment();

一旦v1v2struct。它是否真的取决于 condition 是否为编译时常量?


1
你说得对,当它是一个结构体时,它会创建一个副本。这就是为什么可变结构体是有害的。https://dev59.com/0XRC5IYBdhLWcg3wAcM3 - juharr
1
C#编译器并不执行很多优化,但它确实处理像这样的常量表达式。这种古怪的行为是为什么你通常会在SO上看到“不要改变结构!”的建议。并不是很好看,值类型在C#中是一个泄漏的抽象。我认为你应该点击New Issue按钮,让微软工程师来权衡这个问题。我怀疑他们会修复它,但谁知道呢。 - Hans Passant
1个回答

1

按照建议,我已向微软发送了错误报告,结果发现标准并没有明确说明条件运算符的结果是r-value (值)还是l-value (变量)。根据标准中其他内容的传递性,似乎结果应该是一个r-value

决定修复此问题,修复程序已经在路上了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接