C# 在多重赋值中丢失中间值

标签 c#

鉴于...

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++ 的行为,并假设我需要接受教育。我了解表达式评估逻辑的方式,不需要解释 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;

我不喜欢它 - 郑重声明 - 因为它打破了我的直觉;-)

最佳答案

它也不能保证在 C/C++ 中工作。在单个语句中多次赋值的变量的值是未定义的。

它是否有效取决于实现 - 您可能会发现它根本不起作用的编译器或架构。

C# 只是对此很严格,这并不是坏事。

无论如何,xor 技巧在现代架构上毫无意义。底层实现的效率将低于仅使用临时变量。现代 CPU 上有 2 个以上的寄存器。

关于C# 在多重赋值中丢失中间值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13540480/

相关文章:

c# - asp.net 中的动态调查表

c# - 如何判断XmlTextReader已经读取了多少数据?

c# - Entity Framework 迁移 - Alter Table 语句与外键约束冲突

c# - 尝试在 WCF 中序列化时出现 System.StackOverflowException

c# - ORA-01013 : user requested cancel of current operation

C# Gridview,重新排列

C#内置队列比我自己的快

c# - WCF 3.5 和 UDP

c# - 读取大型 xml 文件并将其数据提取到 C#.Net 项目中的表单应用程序中

c# - 捕获事件窗口更改事件时出现问题