Why does this assigning produce a comile error: Constant value '-2147483648' cannot be converted to a 'ulong'
and I have to use unchecked (...)
for this case?
ulong xDummy30 = (1 << 30); // works
ulong xDummy31 = (1 << 31); // ERROR 25 Constant value '-2147483648' cannot be converted to a 'ulong'
ulong xDummy32 = (1 << 32); // works
Using this instead works:
ulong xDummy31a = unchecked((ulong)(1 << 31));
// or
ulong xDummy31b = (1ul << 31); // comment from Regis Portalez
Edit
The Question Why do I have to cast 0 (zero) when doing bitwise operations in C#? has a similar answer and the reason for the observed behaviour is the same. But they are different questions.
According to MSDN ulong reference all your integer literals 1, 30, 31 are regarded as int:
When an integer literal has no suffix, its type is the first of these types in which its value can be represented: int, uint, long,
According to MSDN << operator the result of the << operation is also an int. When yo shift by 30 the result is positive, when shifting by 31 the result is a negative int which can't be assigned to an ulong.
Edit: HVD pointed me an error in the following. Thanks HVD!
Start Error - When shifting 32 bits, the compiler knows you want an ulong, and thus the result of the shift operation is a positive long, which can be converted to an unlong - end error
The correct reason why 1<<32 does not lead to compiler error is in the provided link to operator <<:
If the first operand is an int, the shift count is given by the low-order five bits of the second operand. That is, the actual shift count is 0 to 31 bits.
32 to binary: 0010 0000; low order five bits: 0 0000, So the actual performed shift is 1 << 0, which results to the int with the value 1, which of course can be assigned to an ulong.
To solve this, make sure that your number 1 is a long. In that case 1<<31 is still a positive long.
You can also use suffixes to specify the type of the literal according to the following rules: If you use L, the type of the literal integer will be either long or ulong according to its size.
So 1L is a long; 1L <<31 is a positive long, and thus can be assigned to an ulong