tags:

views:

130

answers:

4

If I have two bytes a and b, how come:

byte c = a & b;

produces a compiler error about casting byte to int? It does this even if I put an explicit cast in front of a and b.

Also, I know about this question, but I don't really know how it applies here. This seems like it's a question of the return type of operator &(byte operand, byte operand2), which the compiler should be able to sort out just like any other operator.

+6  A: 

Why do C#'s bitwise operators always return int regardless of the format of their inputs?

I disagree with always. This works and the result of a & b is of type long:

long a = 0xffffffffffff;
long b = 0xffffffffffff;
long x = a & b;

The return type is not int if one or both of the arguments are long, ulong or uint.


Why do C#'s bitwise operators return int if their inputs are bytes?

The result of byte & byte is an int because there is no & operator defined on byte. (Source)

An & operator exists for int and there is also an implicit cast from byte to int so when you write byte1 & byte2 this is effectively the same as writing ((int)byte1) & ((int)byte2) and the result of this is an int.

Mark Byers
True, but that doesn't explain why the result is **int**.
Philippe Leybaert
@Philippe Leybaert: Added extra paragraph.
Mark Byers
huh? it explains exactly and unequivocally why the result is int.
fearofawhackplanet
@fearofawhackplanet: yes, now it does. But not before the extra paragraph was added
Philippe Leybaert
This is a very complete and through answer, although I find it interesting that the `~` operator for a signed 32-bit int works with the number as if it was unsigned 8-bit bytes.
MiffTheFox
+1  A: 

It's because & is defined on integers, not on bytes, and the compiler implicitly casts your two arguments to int.

Mau
+3  A: 
Philippe Leybaert
Basically, it's because the C# designers determined the cost was too high to write a separate the rule for bitwise operators (which cannot overflow) from that for arithmetic operators (which can). It's trivial to show that having the compiler insert an implicit cast is safe, because the value is always in range of the narrower type. But apparently the costs of specifying, writing, and testing that behavior were deemed greater than the benefit.
Ben Voigt
Actually, it has nothing to do with bitwise operators or not. There are simply no operators that act on byte types.
Philippe Leybaert
+1 for link to specs.
Mark Byers
+1  A: 

This behavior is a consequence of the design of IL, the intermediate language generated by all .NET compilers. While it supports the short integer types (byte, sbyte, short, ushort), it has only a very limited number of operations on them. Load, store, convert, create array, that's all.

The binary comparison and branch operations only work on int32, int64, native int, native floating point, object and managed reference. These operands are 32-bits or 64-bits on any current CPU core, ensuring the JIT compiler can generate efficient machine code.

You can read more about it in the Ecma 335, Partition I, chapter 12.1 and Partition III, chapter 1.5

Hans Passant