鉴于...
int a = 1, b = 4;
然后...
a += b += a += b;
在 C++ 中评估...
(a += (b += (a += b))); // a = 14[5 + 9] (b = 9[4 + 5] (a = 5[1 + 4]))
...在 C# 中...
(a += (b += (a += b))); // a = 10[1 + 9] (b = 9[4 + 5] (a = 5[1 + 4]))
// ^ re-use of original value of a (1)
// instead of expected intermediate right-to-left
// evaluation result (5)
以上内容已经在 Visual Studio 2008 和 2012 中测试过,因此不怀疑最近引入的语言错误。
但是,我确实希望 C# 的行为能够模仿 C++,并假设我需要接受教育。我了解表达式评估逻辑的 HOW,不需要 MSIL 解释。在进行了相当广泛的搜索后,未能在语言规范中找到相关的细则,我希望语言专家能解释为什么会这样。
对于那些想知道我到底为什么要这样做的好奇者......有一个方便的小 C++ 技巧,可以对两种整数类型进行非常高效和整洁的内联交换,就像这样......
a ^= b ^= a ^= b;
我很失望地发现它在 C# 中不起作用并且很好奇为什么。这是关于理解 C# 的低级机制及其背后的基本原理。没有更多,没有更少,特别是没有可读性宗教。
请注意
,伙计们,这不是把所有东西都挤在一条线上的认真努力!!!
对于 C(和后来的 C++),运算符优先级和关联性总是被精确定义。赋值运算符的标准从右到左关联性使 C/C++ 版本的行为 100% 清晰且可预测。它在几个编译器和平台上都对我有用,我认为没有像这样表现的编译器是有问题的。
我承认代码行被混淆了,这是一种好奇心,并被用作我可能给初级 C/C++ 程序员的“脑筋急转弯”。显然 C# 是不同的——而且显然是故意的。
我寻求对导致 C# 与其一种祖先语言的行为分歧的设计考虑进行解释。即使有根据的猜测也会受到欢迎。
感谢 Alexander Stepaniuk 的回答。
从操作数的从左到右求值开始
a = 1 + theRest1 // (1)
theRest1 = b = 4 + theRest2 // (2)
theRest2 = a = 1 + 4 // (3)
(3) into (2): theRest1 = b = 4 + 5
(2) into (1): a = 1 + 9
“为什么”的解释仍然值得赞赏。
但 C# 规范清楚,以上是正确的评估。
下面是尽可能接近(我认为)使用 2 个变量的 C++ 技巧......
b ^= a ^= b;
a ^ = b;
我不喜欢它——为了记录——因为它打破了我的直觉;-)