看看这段c#代码:

byte x = 1;
byte y = 2;
byte z = x + y; // ERROR: Cannot implicitly convert type 'int' to 'byte'

在字节(或短)类型上执行的任何数学运算的结果都隐式地转换回整数。解决方案是显式地将结果转换回一个字节:

byte z = (byte)(x + y); // this works

我想知道的是为什么?是建筑吗?哲学吗?

我们有:

Int + Int = Int 长+长=长 浮+浮=浮 Double + Double = Double

所以为什么不呢:

字节+字节=字节 空头+空头=空头?

一点背景知识:我正在对“小数字”(即< 8)执行一个长列表的计算,并将中间结果存储在一个大数组中。使用字节数组(而不是int数组)更快(因为缓存命中)。但是大量的字节强制转换散布在代码中,使得代码更加难以阅读。


当前回答

C#

ECMA-334指出,只有在int+int、uint+uint、long+long和ulong+ulong (ECMA-334 14.7.4)上,加法才被定义为合法。因此,这些是关于14.4.2需要考虑的候选操作。由于存在从byte到int、uint、long和ulong的隐式强制转换,所有加法函数成员都是14.4.2.1下适用的函数成员。我们必须根据14.4.2.3中的规则找到最佳隐式转换:

将(C1)转换为int(T1)比将(C2)转换为uint(T2)或ulong(T2)更好,因为:

如果T1是int, T2是uint或ulong, C1是更好的转换。

将(C1)转换为int(T1)比将(C2)转换为long(T2)更好,因为从int转换为long存在隐式转换:

如果存在从T1到T2的隐式转换,且不存在从T2到T1的隐式转换,则C1是更好的转换。

因此使用int+int函数,该函数返回int型。

可以说它深埋在c#规范中。

CLI

CLI只对6种类型(int32、native int、int64、F、O和&)起作用。(ECMA-335分区3节1.5)

Byte (int8)不是这些类型之一,在添加之前会自动强制转换为int32。(ECMA-335分区3节1.6)

其他回答

这是由于溢出和携带。

如果您将两个8位数字相加,它们可能会溢出到第9位。

例子:

  1111 1111
+ 0000 0001
-----------
1 0000 0000

我不确定,但我假设int型、long型和double型被赋予了更多的空间,因为它们确实相当大。此外,它们是4的倍数,这对计算机来说更有效,因为内部数据总线的宽度是4字节或32位(64位现在越来越普遍)宽。Byte和short的效率稍低,但它们可以节省空间。

我想我以前在什么地方见过这个。从这篇文章,旧的新事物:

假设我们生活在一个幻想的世界 对'byte'的操作导致了什么 “字节”。

byte b = 32;
byte c = 240;
int i = b + c; // what is i?

在这个幻想世界里,i的值 应该是16岁!为什么?因为这两个 +操作符的操作数都是 字节,因此“b+c”的和计算为 一个字节,由于 整数溢出。(而且,正如我所指出的 之前,整数溢出是新的 安全攻击向量。)

编辑:Raymond实质上是在捍卫C和c++最初采用的方法。在评论中,他从语言向后兼容的角度为c#采用了相同的方法进行了辩护。

C#

ECMA-334指出,只有在int+int、uint+uint、long+long和ulong+ulong (ECMA-334 14.7.4)上,加法才被定义为合法。因此,这些是关于14.4.2需要考虑的候选操作。由于存在从byte到int、uint、long和ulong的隐式强制转换,所有加法函数成员都是14.4.2.1下适用的函数成员。我们必须根据14.4.2.3中的规则找到最佳隐式转换:

将(C1)转换为int(T1)比将(C2)转换为uint(T2)或ulong(T2)更好,因为:

如果T1是int, T2是uint或ulong, C1是更好的转换。

将(C1)转换为int(T1)比将(C2)转换为long(T2)更好,因为从int转换为long存在隐式转换:

如果存在从T1到T2的隐式转换,且不存在从T2到T1的隐式转换,则C1是更好的转换。

因此使用int+int函数,该函数返回int型。

可以说它深埋在c#规范中。

CLI

CLI只对6种类型(int32、native int、int64、F、O和&)起作用。(ECMA-335分区3节1.5)

Byte (int8)不是这些类型之一,在添加之前会自动强制转换为int32。(ECMA-335分区3节1.6)

我认为这是一个关于哪种操作更常见的设计决策……如果byte+byte = byte,可能更多的人会被强制转换为int类型的结果所困扰。

我怀疑c#实际上是在调用int上定义的运算符+(它返回一个int,除非你在一个检查块中),并隐式地将你的bytes/shorts都转换为int。这就是为什么行为看起来不一致。