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