## Why is this an issue?

The shifting operators are used to do an arithmetic shift to the bits of an integral numeric value, either to the left or the right.

    var number = 14;         // ...01110 (14)
    var left = number << 1;  // ...11100 (28)
    var right = number >> 1; // ...00111 (7)

Therefore, shifting an integral number by 0 is equivalent to doing nothing, since the bits do not move any positions to the left or the right.

On the other hand, shifting an integral number by a value greater than their count of bits minus one (`n_bits-1`) is equivalent to shifting by the value modulo the bit count of the number (`value % n_bits`).

In the case of `int` and `uint`, which take 32 bits in the memory, the shift count is given by the five low-order bits of the second operand, which can represent numbers from 0 to 31. This means that numbers having the same five low-order bits are treated the same by the shift operators.

    var one =         0b0_00001;
    var thirtyThree = 0b1_00001; // Same five low-order bits, 33 % 32 = 1

    var shifted1 = 42 << one;           // Results in 84
    var shifted2 = 42 << thirtyThree;   // Results in 84

Note that integral number with a less than 32-bit quantity (e.g. `short`, `ushort`) are implicitly converted to `int` before the shifting operation and so the rule for `int`/`uint` applies.

If the first operand is a `long` or `ulong` (64-bit quantity), the shift count is given by the six low-order bits of the second operand. That is, the actual shift count is 0 to 63 bits.

### Exceptions

This rule doesn’t raise an issue when the shift by zero is obviously for cosmetic reasons:

- When the value shifted is a literal.
- When there is a similar shift at the same position on line before or after. E.g.:

    bytes[loc+0] = (byte)(value >> 8);
    bytes[loc+1] = (byte)(value >> 0);

## How to fix it

### Code examples

#### Noncompliant code example

    short s = 1;
    short shortShift1 = (short)(s << 0); // Noncompliant: the value does not change
    short shortShift2 = (short)(s << 33); // Noncompliant: this is equivalent to shifting by 1

    int i = 1;
    int intShift = i << 33; // Noncompliant: this is equivalent to shifting by 1

    long lg = 1;
    long longShift1 = lg << 0; // Noncompliant: the value does not change
    long longShift2 = lg << 65; // Noncompliant: this is equivalent to shifting by 1

#### Compliant solution

    short s = 1;
    short shortShift1 = s;
    short shortShift2 = (short)(s << 1);

    int i = 1;
    var intShift = i << 1;

    long lg = 1;
    var longShift1 = lg;
    var longShift2 = lg << 1;

## Resources

### Documentation

- Microsoft Learn - Bitwise and shift operators (C# reference)
- Wikipedia - Arithmetic shift
- Wikipedia - Modulo