The and is already present in the CIL code emitted by the C# compiler:
IL_0009: ldc.i4.s 31
IL_000b: and
IL_000c: shl
The spec for the CIL shl instruction says:
The return value is unspecified if shiftAmount is greater than or equal to the size of value.
The C# spec, however, defines the 32-bit shift to take the shift count mod 32:
When the type of x is
intoruint,the shift count is given by the low-order five bits of count. In other words, the shift count is computed fromcount & 0x1F.
In this situation, the C# compiler can’t really do much better than emit an explicit and operation. Best you can hope for is that the JITter will notice this and optimize away the redundant and, but that takes time, and the speed of JIT is pretty important. So consider this the price paid for a JIT-based system.
The real question, I guess, is why the CIL specifies the shl instruction that way, when C# and x86 both specify the truncating behaviour. That I do not know, but I speculate that it’s important for the CIL spec to avoid specifying a behaviour that may JIT to something expensive on some instruction sets. At the same time, it’s important for C# to have as few undefined behaviours as possible, because people invariably end up using such undefined behaviours until the next version of the compiler/framework/OS/whatever changes them, breaking the code.