开发者

How to Subtract Bytes on One Line in C#

开发者 https://www.devze.com 2023-02-02 05:42 出处:网络
This is really odd.Can anyone explain this? This code does NOT work: const byte ASC_OFFSET = 96; string Upright = \"firefly\";

This is really odd. Can anyone explain this?

This code does NOT work:

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

This code also does NOT work:

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

Yet, putting the subtraction on a separate line works just fine:

const byte ASC_OFFSET = 96;
st开发者_如何学编程ring Upright = "firefly";
byte c7 = (byte)Upright[6];
c7 -= ASC_OFFSET;

I don't mind putting the statements on separate lines, if I have to... but I have to wonder...

Why?


This is because 1) byte operations result in int (see why here: http://blogs.msdn.com/b/oldnewthing/archive/2004/03/10/87247.aspx) and 2) the following C# code

c7 -= ASC_OFFSET;

will be "magically" compiled behind the scene into

c7 = (byte)(c7 - ASC_OFFSET);

This is explicitely documented in C# specification here: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf

14.14.2 Compound assignment:

An operation of the form x op= y is processed by applying binary operator overload resolution (§14.2.4) as if the operation was written x op y. Then,

• If the return type of the selected operator is implicitly convertible to the type of x, the operation is evaluated as x = x op y, except that x is evaluated only once.

Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x, and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y), where T is the type of x, except that x is evaluated only once.

• Otherwise, the compound assignment is invalid, and a compile-time error occurs


The reason why your first two samples do not compile is because:

  • The cast binds "tighter" than the subtraction. That is, '(C)d-e' means '((C)d)-e', not '(C)(d-e)'. The cast operator is higher precedence.
  • Therefore the type of both operands to the subtraction is byte, regardless of the casts.
  • The type of the subtraction is int, because there is no subtraction operator defined on bytes.
  • Therefore, you are assigning an int to a byte without a cast, which is illegal.

There is no subtraction operator on bytes because, well, suppose you have a byte containing 7 and you subtract from it a byte containing 8, do you really want that to be the byte 255? I think most people would want that to be the int -1.

Finally, why on earth are you doing this in bytes in the first place? This doesn't make any sense. Chars aren't bytes in C#; if you want to do arithmetic on chars then why not subtract the char 96 from the char 'y' instead of doing a lossy and dangerous conversion to byte?


I've noticed this before too. I think it's because the -= operator is predefined for byte types, whereas in the former cases, you're really putting an int inside a byte, which isn't allowed. The reason they did this doesn't necessarily make sense, but it's consistent with the rules, because in the former cases, the compiler can't "peek" at the - operator when doing the assignment.

If you really need to subtract on one line, instead of saying:

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

Say:

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

精彩评论

暂无评论...
验证码 换一张
取 消