C# Bitwise Operations — Digitteck
C# Bitwise Operations
dotnet·28 April 2021·3 min read

C# Bitwise Operations

Bitwise operations are important when dealing with permissions. In this scenario, permissions are designed as flags — a single variable can hold one or multiple permissions, all described in an enum decorated with [Flags].

csharp
[Flags]
public enum Flags : long
{
    T1_CanDelete = 2 << 0,
    T1_CanEdit   = 2 << 1,
    T2_CanDelete = 2 << 2
}

Or Operation

Combine multiple permissions with the | operator. Each pair of bits is set to 1 if either bit is 1:

csharp
// Combine permissions with OR
var op1 = Flags.T1_CanDelete | Flags.T1_CanEdit;

// Visualize bits
Console.WriteLine(Convert.ToString((int)Flags.T1_CanDelete, 2).PadLeft(8, '0')); // 00000010
Console.WriteLine(Convert.ToString((int)Flags.T1_CanEdit,   2).PadLeft(8, '0')); // 00000100
Console.WriteLine(Convert.ToString((int)op1,                2).PadLeft(8, '0')); // 00000110

And Operation

To check if a flag is set, use the bitwise & operator rather than HasFlag — it checks if both bits are 1 and is more performant:

csharp
// HasFlag — convenient but less performant
Console.WriteLine(op1.HasFlag(Flags.T1_CanDelete));

// Bitwise AND — more performant
bool hasFlag = (op1 & Flags.T1_CanDelete) != 0;

// Visualize: only 1 if BOTH bits are 1
Console.WriteLine(Convert.ToString((int)op1,                          2).PadLeft(8, '0')); // 00000110 (op1)
Console.WriteLine(Convert.ToString((int)Flags.T1_CanDelete,           2).PadLeft(8, '0')); // 00000010 (flag)
Console.WriteLine(Convert.ToString((int)(op1 & Flags.T1_CanDelete),   2).PadLeft(8, '0')); // 00000010 (result)

Removing a Flag — Wrong Way

XOR (^) cannot be used to reliably remove a flag — it acts as a toggle. Applying it twice with the same flag restores the original value:

csharp
// XOR acts as a toggle — applying it twice restores the original value
Console.WriteLine(Convert.ToString((int)Flags.T1_CanDelete,           2).PadLeft(8, '0')); // 00000010
Console.WriteLine(Convert.ToString((int)op1,                          2).PadLeft(8, '0')); // 00000110

op1 = op1 ^ Flags.T1_CanDelete;
Console.WriteLine(Convert.ToString((int)op1,                          2).PadLeft(8, '0')); // 00000100 (toggled off)

op1 = op1 ^ Flags.T1_CanDelete;
Console.WriteLine(Convert.ToString((int)op1,                          2).PadLeft(8, '0')); // 00000110 (toggled back on)

Removing a Flag — Correct Way

Use the bitwise complement operator ~ to invert all bits of the target flag, then & to mask it out. The inverted flag ensures the target bit becomes 0 in the result:

csharp
// Use bitwise complement (~) to invert flag bits, then AND to clear them
op1 = Flags.T2_CanDelete | Flags.T1_CanEdit | Flags.T2_CanDelete;

Console.WriteLine(Convert.ToString((int)op1,                            2).PadLeft(8, '0')); // 00001100 (op1)
Console.WriteLine(Convert.ToString((int)Flags.T2_CanDelete,             2).PadLeft(8, '0')); // 00001000 (flag)
Console.WriteLine(Convert.ToString((int)~Flags.T2_CanDelete,            2).PadLeft(8, '0')); // 11110111 (masked)
Console.WriteLine(Convert.ToString((int)((~Flags.T2_CanDelete) & op1),  2).PadLeft(8, '0')); // 00000100 (result)

Tags

.NETC#FlagsBitwise
digitteck

© 2026 Digitteck