6

这真的很奇怪。谁能解释一下?

此代码不起作用:

const byte ASC_OFFSET = 96;
string Upright = "firefly";
byte c7 = (byte)Upright[6] - ASC_OFFSET;
//Cannot implicitly convert type 'int' to 'byte'.

此代码也不起作用:

const byte ASC_OFFSET = 96;
string Upright = "firefly";
byte c7 = (byte)Upright[6] - (byte)ASC_OFFSET;
//Cannot implicitly convert type 'int' to 'byte'.

然而,将减法放在单独的行上就可以了:

const byte ASC_OFFSET = 96;
string Upright = "firefly";
byte c7 = (byte)Upright[6];
c7 -= ASC_OFFSET;

如果必须的话,我不介意将这些陈述放在不同的行中……但我不得不怀疑……

为什么?

4

3 回答 3

7

这是因为 1)byte操作导致int(在此处查看原因:http: //blogs.msdn.com/b/oldnewthing/archive/2004/03/10/87247.aspx)和 2) 以下 C# 代码

c7 -= ASC_OFFSET;

会在幕后“神奇”地编译成

c7 = (byte)(c7 - ASC_OFFSET);

这在 C# 规范中有明确记录:http: //www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf

14.14.2 复合赋值:

通过应用二元运算符重载决议(第 14.2.4 节)来处理 x op= y 形式的操作,就好像该操作写成 x op y。然后,

• 如果所选运算符的返回类型可隐式转换为 x 的类型,则运算的计算结果为 x = x op y,但 x 仅计算一次。

否则,如果所选运算符是预定义运算符,如果所选运算符的返回类型可显式转换为 x 的类型,并且如果 y 可隐式转换为 x 的类型或运算符是移位运算符,则运算被计算为 x = (T)(x op y),其中 T 是 x 的类型,除了 x 只被计算一次。

• 否则,复合赋值无效,并出现编译时错误

于 2011-01-02T07:58:41.463 回答
5

您的前两个示例无法编译的原因是:

  • 强制转换比减法绑定“更紧密”。也就是说,“(C)de”表示“((C)d)-e”,而不是“(C)(de)”。强制转换运算符具有更高的优先级。
  • 因此,减法的两个操作数的类型都是字节,而与强制转换无关。
  • 减法的类型是 int,因为没有在字节上定义减法运算符。
  • 因此,您将 int 分配给没有强制转换的字节,这是非法的。

字节上没有减法运算符,因为,假设您有一个包含 7 的字节,然后从中减去一个包含 8 的字节,您真的希望它是 255 字节吗?我想大多数人都希望它是 int -1。

最后,为什么你首先要以字节为单位?这没有任何意义。C# 中的字符不是字节;如果您想对 char 进行算术运算,那么为什么不从 char 'y' 中 减去char 96 而不是进行有损且危险的字节转换呢?

于 2011-01-02T16:30:26.887 回答
4

我以前也注意到了这一点。我认为这是因为-=运算符是为字节类型预定义的,而在前一种情况下,您实际上是int在 a 内部放置了一个byte,这是不允许的。他们这样做的原因不一定有意义,但它符合规则,因为在前一种情况下,编译器-在进行赋值时无法“窥视”运算符。

如果你真的需要减去一行,而不是说:

byte c7 = (byte)Upright[6] - ASC_OFFSET;

说:

byte c7 = (byte)(Upright[6] - ASC_OFFSET);
于 2011-01-02T07:31:12.683 回答