如何在C#中减去一行的字节数

时间:2011-01-02 07:28:58

标签: c# compiler-construction language-construct

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

此代码不起作用:

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;

我不介意将这些陈述分开,如果我必须......但我不得不怀疑......

为什么吗

3 个答案:

答案 0 :(得分: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复合赋值:

     

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

     

•如果返回类型   选择的运算符是隐含的   可转换为x的类型   操作被评估为x = x op y,   除了x只评估一次。

     

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

     

•   否则,复合赋值是   无效,编译时错误   发生

答案 1 :(得分:4)

前两个样本无法编译的原因是:

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

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

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

答案 2 :(得分:3)

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

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

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

说:

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