- Advanced C# Tips: Don’t Use unsafe for Minor Gains
- Advanced C# Tips: Use ‘in’ Parameter Modifier for Large Value Types
- Advanced C# Tips: Prefer Structs for Immutable Data
- Advanced C# Tips: Prefer Value Types Over Reference Types
- Advanced C# Tips: Use Exceptions Wisely
- Advanced C# Tips: Consider Leveraging Bitwise Operations for Simple Calculations If Possible
- Advanced C# Tips: Utilize ArrayPool for Frequent Array Allocations
- Advanced C# Tips: Reuse Objects Where Possible

Bitwise operators in C# are special tools that let you work directly with the individual bits of a number’s binary representation. If you are reading this blog post, I assume you also know that in computing world, numbers are actually stored as sequences of bits. Bitwise operators allow you to perform operations on these sequences bit by bit. They are like the switches that can flip the bits in certain patterns. They allow for a variety of operations such as flipping bits on and off, shifting them left or right, or comparing two values bit by bit. However we can’t use bitwise operators for every occasion, this is why I added the statement “if possible”. On the other hand, always bare in mind not to use over-optimization for minor gains since they add more complexity.

These operators include & (bitwise AND), | (bitwise OR), ^ (bitwise XOR), ~ (bitwise NOT), << (left shift), and >> (right shift). Each of these performs a specific operation on two binary values, except for the NOT operator, which works on just one. They are used in scenarios where you need to manipulate flags, encode and decode data compactly, or when you’re performing certain mathematical operations that can be optimized by operating directly on bits.

Using bitwise operations can cause significant amount performance optimization because they are among the simplest and fastest operations a computer can perform. They happen directly on the CPU level even without the need to go through a higher-level. For example, checking whether a number is odd or even using bitwise operations is way faster than using division or modulus because you only need to look at the last bit of a binary number to know if it’s odd or even. The technical reason bitwise operations are faster is that they avoid the overhead of the logical operations that involve branching and more complex logic. A bitwise AND (&) operation for example, goes through each bit of two numbers and sets the corresponding bit in the result to 1 if both bits are 1. This can be done very quickly in parallel for all bits in a CPU register, making it much faster than a sequence of conditional statements.

Let’s look at some simple code examples:

Using logical operators for conditional checks:

`bool isEven = (number % 2) == 0;`

Using bitwise operators for the same check:

`bool isEven = (number & 1) == 0;`

In the first example, % is the modulus operator, which involves division will be a relatively slow operation. The second example uses a bitwise AND, which is much faster as it only checks the last bit of the number.

Another example could be setting or clearing specific bits that might represent features in a configuration setting:

Setting a Bit with Bitwise OR:

```
// Binary representation for 9
int settings = 0b_1001;
// Mask to set a particular bit (2nd bit from the right)
int mask = 0b_0100;
// Sets the 2nd bit to 1
settings = settings | mask;
```

Clearing a Bit with Bitwise AND and NOT:

```
// Invert mask to clear a particular bit (2nd bit from the right)
int mask = ~(0b_0100);
// Clears the 2nd bit to 0
settings = settings & mask;
```

In these examples, bitwise operations are used to manipulate individual bits within an integer to turn certain features on or off. This approach is way faster than other methods of checking and setting these conditions and is a common practice in low-level programming and systems where performance is critical.

The first criticism against using bitwise operators might be sacrificing the readability. I can’t say I don’t agree with that. This is why we need to use it wisely. You may want to re-consider if using bitwise operators really makes code difficult to understand. Keep it as a tool in your toolbox but use it wisely. Don’t make your code too complicated for the sake of little gains.

Suleyman Cabir Ataman, PhD