Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitwise operations, ulong and int

I just discovered that C# will not let you perform bitwise operations on a ulong and an int. Every other combination of int, uint, long, and ulong will work, but that one pairing doesn't.

However, if instead of an int, I have a const int, everything is fine.

What's going on here? Why is int & ulong invalid, but const int & ulong valid?


Broken:

int mask = 0x1110;
ulong value = 0x1010;

var result = mask & value; // Compilation error: "Operator '&' cannot be applied to operands of type 'int' and 'ulong'"

Working:

const int mask = 0x1110;
ulong value = 0x1010;

var result = mask & value; // Works just fine.
like image 380
Bobson Avatar asked Dec 14 '16 15:12

Bobson


1 Answers

This behavior is not specific to bitwise operations. According to C# Language Specification, it applies to all binary operations requiring numeric promotions.

Section 7.6.3.2 describes binary numeric promotions. I emphasized the section that specifies the behavior that you see:

Binary numeric promotion consists of applying the following rules, in the order they appear here:

  • If either operand is of type decimal, the other operand is converted to type decimal, or a binding-time error occurs if the other operand is of type float or double.
  • Otherwise, if either operand is of type double, the other operand is converted to type double.
  • Otherwise, if either operand is of type float, the other operand is converted to type float.
  • Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a binding-time error occurs if the other operand is of type sbyte, short, int, or long.
  • Otherwise, if either operand is of type long, the other operand is converted to type long.
  • Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.
  • Otherwise, if either operand is of type uint, the other operand is converted to type uint.
  • Otherwise, both operands are converted to type int.

The reason the problem does not happen when you use const is that the compiler is allowed to convert const int expression to other types, as described in section 7.19:

An implicit constant expression conversion (§6.1.9) permits a constant expression of type int to be converted to sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant expression is within the range of the destination type.

Since the value of mask, i.e. 0x1110, fits within ulong, the compiler performs the promotion instead of triggering the error.

like image 75
Sergey Kalinichenko Avatar answered Sep 19 '22 13:09

Sergey Kalinichenko