为什么C#的二元运算符总是返回int而不管它们的输入格式如何?

Why do C#'s binary operators always return int regardless of the format of their inputs?

如果我有两个byteab,怎么会:

1
byte c = a & b;

生成有关将字节强制转换为int的编译器错误?即使我在ab前面放了一个明确的演员表,也能做到这一点。

另外,我知道这个问题,但我不知道它在这里是如何应用的。这似乎是operator &(byte operand, byte operand2)的返回类型的问题,编译器应该能够像其他任何操作符一样进行排序。


Why do C#'s bitwise operators always return int regardless of the format of their inputs?

我总是不同意。本工程及a & b成果为long型:

1
2
3
long a = 0xffffffffffff;
long b = 0xffffffffffff;
long x = a & b;

如果其中一个或两个参数是longulonguint,则返回类型不是int

Why do C#'s bitwise operators return int if their inputs are bytes?

byte & byte的结果是一个int,因为字节上没有定义&运算符。(源)

int有一个&操作符,也有一个从byteint的隐式强制转换,所以当你写byte1 & byte2时,这实际上与写((int)byte1) & ((int)byte2)相同,其结果是int


这种行为是所有.NET编译器生成的中间语言IL设计的结果。虽然它支持短整型(byte、sbyte、short、ushort),但对它们的操作数量非常有限。只需加载、存储、转换、创建数组。这不是意外,这是一种可以在32位处理器上高效执行的操作,早在IL设计和RISC成为未来的时候。

二进制比较和分支操作仅在Int32、Int64、Native int、Native浮点、对象和托管引用上工作。这些操作数在任何当前CPU核心上都是32位或64位,确保JIT编译器能够生成高效的机器代码。

您可以在ECMA 335第I部分第12.1章和第III部分第1.5章中了解更多有关它的信息。

我在这里写了一篇更广泛的文章。


没有为字节类型(以及其他类型)定义二进制运算符。事实上,所有二进制(数字)运算符仅对以下本机类型起作用:

  • int
  • 无符号整型
  • 长的
  • 无符号长整型
  • 浮动
  • 双重的
  • 十进制的

如果涉及任何其他类型,它将使用上述类型之一。

所有这些都在C规范版本5.0(第7.3.6.2节)中:

对预定义的+、–、*、/、%、&;、、^、=、!=、>、<、>=和<=二进制运算符。二进制数字提升将两个操作数隐式转换为一个公共类型,对于非关系运算符,该类型也将成为操作的结果类型。二进制数字提升包括按以下规则在此处出现的顺序应用它们:

  • 如果其中一个操作数是decimal类型,则另一个操作数将转换为decimal类型,如果另一个操作数是float或double类型,则会发生编译时错误。
  • 否则,如果其中一个操作数是double类型,则另一个操作数将转换为double类型。
  • 否则,如果其中一个操作数是float类型,则另一个操作数将转换为float类型。
  • 否则,如果其中一个操作数是ulong类型,则另一个操作数将转换为ulong类型,如果另一个操作数是sbyte、short、int或long类型,则会出现编译时错误。
  • 否则,如果其中一个操作数是long类型,则另一个操作数将转换为long类型。
  • 否则,如果其中一个操作数是uint类型,而另一个操作数是sbyte、short或int类型,则两个操作数都将转换为long类型。
  • 否则,如果其中一个操作数是uint类型,则另一个操作数将转换为uint类型。
  • 否则,两个操作数都将转换为int类型。


这是因为&;是在整数上定义的,而不是在字节上定义的,编译器将您的两个参数隐式地强制转换为int。