为什么短原语有赋值运算符(&=、+=)但没有非赋值运算符(&、+)?

Why are there assignment operators (&=, +=) but no non-assignment operators (&, +) for short primitives?

我偶然发现小于 32 位的基本类型不允许按位或算术运算的行为,但实际上允许相应的赋值操作:

short BitwiseAnd(short a, short b) { return a & b; }         // error
short BitwiseAndAssignment(ref short a, short b) { a &= b; } // works

short Add(short a, short b) { return a + b; }                // error
short AddAssignment(ref short a, short b) { a += b; }        // works

相同的行为适用于其他短基本类型,如 bytesbyteushort

我知道算术和逻辑运算是为 32 位和更大的类型定义的 (int, long...) 因为这是处理器提供的 (see this question) , 较短的类型被加宽并且可以转换回 8 或 16 位。但是,为什么这会在赋值运算符中起作用?首先我假设在幕后,shorts 被转换为 int,但是你会有一个 assignment/return 值 short value = (some int),这应该会产生一个错误,因为转换不是隐式的。

换个说法:我在Visual Studio的直接window中尝试了一些代码,但似乎有更多的代码可以工作.立即数 window 可能会进行一些通常是显式的隐式转换。例如,立即数 window 中允许 short a = (int)5;。所以这没有帮助。

真正的错误是由于在对它们进行运算时将较小的整数类型隐式转换为 int

当你有 a & b 其中 abshort 时,它们都被转换为 int 并且应用 & 运算符并且结果将是 int 类型,因此您不能在方法声明中将 return int 作为 short。一个简单的转换将解决问题。 (short)(a & b).

short BitwiseAnd(short a, short b) { return (short)(a & b); }  //no error!

当你有

short BitwiseAndAssignment(ref short a, short b) { a &= b; }

编译器将为您生成转换,否则您永远不能在比 int 更小的类型上使用这些运算符(+=*=、...) .


幕后发生了什么??

short a = 1;
short b = 2;

short c = a + b; //error! 

为什么?因为 + 运算符没有重载来接收两个 short 参数。由于存在 shortint 之间的隐式转换,因此方法解析将选择具有两个 int 作为输入参数的重载。所以它将 ab 转换为 int 然后调用选择的重载 returns 一个 int .因为它 return 是一个 int,所以你不能将它存储在 short 变量中,所以你需要明确地转换它。

short c = (short)(a + b)//this will work

However, is there a reason why this would work in an assignment operator?

是:因为否则赋值运算符 永远无法工作 这些类型 - 没有允许它工作的语法。 a += ba &= bexpectation是明确的,所以自动进行转换。

使用 a + ba & b,正如您已经注意到的那样:出于性能原因,这已扩大;存在将其放回去的语法,特别是 (short)(a+b)