# C# Byte/Short Mathematics

N

#### NvrBst

is there anyway to use bytes with numbers without actually casting at
the end?

byte Test = 10;
byte row = Test - 5;

Return Error: Cannot implicitly convert type 'int' to 'byte'. An
explicit conversion exists (are you missing a cast?)

I seen some integer-type-suffix's
ulong Test = 10;
ulong row = Test - 5UL;

But I only found "U" and "L"... meaning a number like "5" in "Test -
5" can only set to int / long (uint / ulong)? Whats the suffix's for
short and byte? Or just have to cast it at the end? (byte)(Test - 5)?

Thanks

P

#### Peter Duniho

[...]
I seen some integer-type-suffix's
ulong Test = 10;
ulong row = Test - 5UL;

But I only found "U" and "L"... meaning a number like "5" in "Test -
5" can only set to int / long (uint / ulong)? Whats the suffix's for
short and byte? Or just have to cast it at the end? (byte)(Test - 5)?

I'm not aware of a specifier to define a byte constant (other than, of
course, making a named constant of type byte).

However, I'll point out that instead of casting the result of your
calculation, you can cast the constant itself so that the entire
calculation is done with bytes:

byte row = Test - (byte)5;

That way, Test isn't promoted to int, and the expression itself winds up
with type byte instead of type int.

Pete

B

#### Ben Voigt [C++ MVP]

NvrBst said:
is there anyway to use bytes with numbers without actually casting at
the end?

byte Test = 10;
byte row = Test - 5;

Return Error: Cannot implicitly convert type 'int' to 'byte'. An
explicit conversion exists (are you missing a cast?)

I seen some integer-type-suffix's
ulong Test = 10;
ulong row = Test - 5UL;

But I only found "U" and "L"... meaning a number like "5" in "Test -
5" can only set to int / long (uint / ulong)? Whats the suffix's for
short and byte? Or just have to cast it at the end? (byte)(Test - 5)?

You have to cast it at the end, because the operands are always promoted.
Even with a byte constant you end up with an int result. Peter is wrong

I'm convinced this is a bug, but it is designed into the C# specification.

J

#### Jon Skeet [C# MVP]

Peter Duniho said:
However, I'll point out that instead of casting the result of your
calculation, you can cast the constant itself so that the entire
calculation is done with bytes:

byte row = Test - (byte)5;

That way, Test isn't promoted to int, and the expression itself winds up
with type byte instead of type int.

No, both are promoted. Try it and see:

using System;

class Test
{
static void Main()
{
byte test = 10;
byte row = test - (byte)5;
}
}

Test.cs(8,20): error CS0266: Cannot implicitly convert type 'int' to
'byte'. An explicit conversion exists (are you missing a cast?)

Basically there's no operator byte +(byte, byte). Instead, the operands
are promoted and int +(int,int) is used.

The exception to this is using += and -= :

using System;

class Test
{
static void Main()
{
byte test = 10;
test += 5;
}
}

P

#### Peter Duniho

[...]
Basically there's no operator byte +(byte, byte). Instead, the operands
are promoted and int +(int,int) is used.

Ugh. Really? Sheesh.

P

#### Peter Duniho

[...]

I'm convinced this is a bug, but it is designed into the C#
specification.

I'll be happy to sign the petition.

J

#### Jon Skeet [C# MVP]

Ugh. Really? Sheesh.

I *believe* it's for performance reasons. Processors natively add 32
bit values together with appropriate overflow handling - adding the 8
bit values and then "manually" handling the overflow would be slower
than just treating them as 32 bit values and letting the user add the
overflow handling *where required*.

At least, that's what I've heard before (from people who know). I'm
not saying it's the best decision in the world - language choices
being affected by performance rarely are - but that's the reason I've
heard used pretty frequently.

Jon

?

Jon said:
I *believe* it's for performance reasons. Processors natively add 32
bit values together with appropriate overflow handling - adding the 8
bit values and then "manually" handling the overflow would be slower
than just treating them as 32 bit values and letting the user add the
overflow handling *where required*.

AFAIK, modern ALUs are even incapable of byte arithmetic.

P

#### Peter Duniho

I *believe* it's for performance reasons. Processors natively add 32
bit values together with appropriate overflow handling - adding the 8
bit values and then "manually" handling the overflow would be slower
than just treating them as 32 bit values and letting the user add the
overflow handling *where required*.

I can understand there being a performance issue. I can't understand the
compiler imposing that on the programmer.

To me, the type promotion as it's applied to the code need not match the
type promotion as it's applied to the implementation. Semantically, it
would make sense to allow adding two bytes, so the operator should exist.
If the implementation of the operator was done to promote both operands,
and then demote the results, I wouldn't have a problem with that. But why
exclude the operator altogether?

Pete