Why can’t I do arithmetic on byte types…

A customer wrote me today to ask, “Why can't I do arithmetic on byte types?” For example, if you write:

byte a = 0x01;
byte b = ~a;

The compiler will complain on the second line that you can't convert an int to a byte. This happens because there are no operations defined for any types smaller than 4-byte types. The question is, “Why?”

Back in the old days, when a 5 MB disk drive was the size of a washing machine and memory was measured in the KB (ie when I went to college), memory and disk storage was very precious, and you did your best to conserve it. But times have changed. If you look at most programs these days, you'll find that they do the vast majority of their operations on 4-byte operands. And, in fact, x86 processors are very good at these operations.

But to get fast at those operations, many processors are slower at accessing smaller-than-4-byte operands, so if you use them you will have a program that's slower to execute.

Given that, the C# and CLR designers decided to only define arithmetic operations on 4-byte and 8-byte operand sizes. It does mean that you have to have some casts when using smaller types, but it's more indicative of what's going on at the chip level.

So, that's what's going on here.

Comments (11)

  1. Jerry Pisk says:

    So not only CLR does not provide abstraction from underlying hardware, it actually forces it on you even more than unmanaged languages (C/C++ come in mind)? I thought the whole goal of CLR was to make the code platform independent…

  2. Sean Terry says:

    Still, I think the compiler should be smart enough to perform the casts implicitly without having to explicitly write them (operands and destination are of the same type… no problem).

    Considering the number of times you have to use byte arrays (e.g., the MemoryStream.Write method) it would be nice to have that flexibility without needing casts all over the place. If I could write an int array to a memory stream, I probably wouldn’t care about the byte needing explicit casts.

  3. W Poust says:

    Legacy code… it’s the white elephant that a lot of us can’t ignore.

    It would nice to cut and paste the critical sections of old algorthims into new code without having to stop and figure out what the compiler is going to do.

  4. Raymond Chen says:

    Imagine what the world would be like if arithmetic operations on "byte" returned "byte".

    byte b = 20;

    byte c = 240;

    // what does this print?



    If you said



    then you are expecting bytes to be promoted to ints in arithmetic operations. If byte operations resulted in byte, the results would have been 236 and 4. Surely you don’t want that, do you?

  5. SBC says:

    any thoughts on masking & shift operations?

  6. Sean Terry says:

    ::Surely you don’t want that, do you?

    That is exactly what I want. I want my byte to behave like a byte when I treat it like like a byte. If I wanted it to act like an int, I would have casted it as such.

    Silly bytes.

  7. slobodan filipovic says:

    to raymond Chen

    It should be 240 and –20.

    After all, you have different operator

    + (Addition binary operator)

    – (Unary)

    & (Bit wise and)

    | (Bit wise or)

    There is no problem at all.

    It will be nice to put it in framework.

    Just like Boolean value type (true, false)

Skip to main content