需要对 byte = byte - byte 进行类型转换吗?

8
我有以下代码:

foreach (byte b in bytes)
{
    byte inv = byte.MaxValue - b;
    // Add the new value to a list....
}

当我这样做时,会出现以下错误:

无法隐式将类型'int'转换为'byte'。存在显式转换(是否缺少强制转换?)

该语句的每个部分都是一个字节。为什么C#要将byte.MaxValue - b转换为int?

难道不能在不进行强制转换的情况下完成吗?(即:我不想这样做:byte inv = (byte) (byte.MaxValue - b);

2个回答

4
根据C#语言参考,右侧的算术表达式默认情况下会评估为int类型,因此可能的原因是处理器访问4字节内存地址比1字节内存地址更快,因此算术运算符被定义为使用4字节操作数。

我猜问题是为什么?当我执行int-int时,它不会产生int64。为什么在byte-byte时自动提升类型? - Vaccano
1
@Vaccano:我猜是为了算术运算符只需要定义与某些长度的操作数(4字节和8字节)一起工作,但这只是我的推测。 - Bill the Lizard
3
即使 MSIL 只支持 2**32 模数算术运算,C# 编译器仍然可以自由地插入缩小转换,以适应将结果存储到与操作数一样狭窄的变量时所必需的情况。 - Ben Voigt
@Ben Voigt:我本能地不希望编译器为我插入缩小转换。然而,在这种情况下,通过将结果分配给一个字节,您隐含地告诉它执行转换。我找不到您逻辑上的任何错误。 - Bill the Lizard
2
我只希望编译器在符合类型系统的情况下插入强制转换。因为在我看来,将byte & byte的结果保存到另一个byte中是类型安全的,编译器可以使用最有效的指令序列来完成这个操作。如果这恰好是一个32位宽的AND操作,然后再进行缩小转换,那么它并没有破坏类型安全性,所以在我看来完全没问题。 - Ben Voigt

2
对于加、乘和减法,有一个相当好的解释:包括进位位在内的计算,然后将它们抛弃比如果一开始就抛弃进位位要容易得多。
对于位运算符(交集、包含并集、排他或运算、补码)这种推理根本站不住脚。我唯一能想到的是,如果你从混合有符号和无符号操作数开始,然后将结果保存在更宽的类型中,扩展符号会有些模棱两可。但这并不能解释为什么位运算符是一元的或所有操作数都具有相同类型时,应将结果扩展为int类型。我认为这是C#的一个非常烦人的设计缺陷:
byte a, b;
byte c = a | b;

生成错误。


1
我同意你的总体观点,但这难道不是 C# 中的“烦人设计缺陷”,而不是 .NET 的问题吗?例如,F# 定义了逻辑和算术操作字节的函数,返回的也是字节。 - kvb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接