Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Logical and Bitwise Operators in C#

Feb 1, 2020 • 8 Minute Read

Introduction

C# supports five main types of operators, which are grouped together based on the idea behind their existence.

Categories of operators:

  1. Arithmetic operators: Perform operations on numbers that are int, double, float, etc.
  2. Relational operators: Compare and check the equality of the input objects
  3. Logical operators: Compare bits of the given object and always return a Boolean result
  4. Bitwise operators: Perform operations on individual bits, and the result is also always a bit
  5. Assignment operators: allow us to initialize an object with a value or perform specific operations on it
  6. Miscellaneous operators

The concept of operator precedence prescribes the logic for how complex expressions are evaluated. This differs by operator category. For a full list, visit the official Microsoft reference.

This guide will discuss bitwise and logical operators, including how you can understand their effect on your code.

Logical Operators

This category of operators works with Boolean variables or expressions. There are three basic operands it allows you to use: AND, OR, and NOT. Every complex logical expression can be built using a combination of these. A truth table can be quickly drawn up to verify the logic and the results, and below we will see the truth table of these operands.

Let's assume 1 means true and 0 means false.

The truth table of the AND and OR operands:

ABANDOR
1001
0101
0000
1111

When you are working with the AND operand, there is a very easy way to understand and calculate the results. The result is always false as long as there is a 0 among the operands and true when both operands are 1.

Working with the OR operand also has its easy way to understand the logic. The result is always true as long as there is a ``* among the operands and false when both operands are 0.

In C#, the && operator means AND, and the || operator means OR.

Let's look at an example of these.

      using System;
namespace Pluralsight
{
    public class LogicalOperators
    {
        public static void Main()
        {
            bool a = true;
            bool b = false;
            Console.WriteLine($"The value of a is {a}, and b is {b}");
            Console.WriteLine($"The a && b evaluates to {a&&b}");
            Console.WriteLine($"The a || b evaluates to {a || b}");
            a = false;
            b = false;
            Console.WriteLine($"The value of a is {a}, and b is {b}");
            Console.WriteLine($"The a && b evaluates to {a && b}");
            Console.WriteLine($"The a || b evaluates to {a || b}");
            a = true;
            b = true;
            Console.WriteLine($"The value of a is {a}, and b is {b}");
            Console.WriteLine($"The a && b evaluates to {a && b}");
            Console.WriteLine($"The a || b evaluates to {a || b}");
            a = false;
            b = true;
            Console.WriteLine($"The value of a is {a}, and b is {b}");
            Console.WriteLine($"The a && b evaluates to {a && b}");
            Console.WriteLine($"The a || b evaluates to {a || b}");
            Console.ReadKey();
        }

    }
}
    

Executing the code gives us the following output.

      The value of a is True, and b is False
The a && b evaluates to False
The a || b evaluates to True
The value of a is False, and b is False
The a && b evaluates to False
The a || b evaluates to False
The value of a is True, and b is True
The a && b evaluates to True
The a || b evaluates to True
The value of a is False, and b is True
The a && b evaluates to False
The a || b evaluates to True
    

The truth table of the NOT operand:

ANOT
10
00

In C#, the ! operator means the NOT operand.

Let's look at a short example as to how it works.

      using System;
namespace Pluralsight
{
    public class LogicalOperators
    {
        public static void Main()
        {
            bool a = true;
            Console.WriteLine($"The value of a is {a}");
            Console.WriteLine($"The !a evaluates to {!a}");
            a = false;
            Console.WriteLine($"The value of a is {a}");
            Console.WriteLine($"The !a evaluates to {!a}");
            Console.ReadKey();
        }

    }
}
    

Executing the code gives us the following result.

      The value of a is True
The !a evaluates to False
The value of a is False
The !a evaluates to True
    

You can also combine these expressions to describe more sophisticated logic in your applications.

Bitwise Operators

This type of operator has two types of variables it can work with. One is the integral numeric type, which hold the sbyte, byte, short, ushort, int, uint, long, and ulong subtypes, and the other is the char type. As long as you are using any of these, the operator is going to work.

There are a total of six bitwise operators:

  1. ~ - Complement (Flips the bits in a bit stream so the 1-s become 0-s and vice versa.)
  2. & - AND (Same logic as in the logical operators section)
  3. | - OR (Same logic as in the logical operators section)
  4. ^ - Exclusive OR (The bit is flipped if there is a 1 in either operand but not both.)
  5. << - Left shift (Moves the bits against the left side by the specified amount.)
  6. >> - Right shift (Moves the bits against the right side by the specified amount.)

We'll demonstrate these operands with two numbers:

DecimalBinary
60000 0110
170001 0001

Let's create the demonstration.

      using System;
namespace Pluralsight
{
    public class LogicalOperators
    {
        public static void Main()
        {
            int a = 6;
            int b = 17;
            Console.WriteLine($"The value of a is {a} in binary: {Convert.ToString(a, 2)}, b is {b} in binary: {Convert.ToString(b, 2)}!");
            Console.WriteLine("Bitwise OR");            
            Console.WriteLine($"The bitwise OR result is {a | b} in binary: { Convert.ToString((a|b), 2)}");
            Console.WriteLine("Bitwise AND");            
            Console.WriteLine($"The bitwise AND result is {a & b} in binary: { Convert.ToString((a & b), 2)}");
            Console.WriteLine("Bitwise Complement");            
            Console.WriteLine($"The bitwise AND result is {~a} in binary: { Convert.ToString((~a), 2)}");
            Console.WriteLine("Bitwise XOR");
            Console.WriteLine($"The bitwise AND result is {a ^ b} in binary: { Convert.ToString((a ^ b), 2)}");
            Console.WriteLine("Bitwise <<");
            Console.WriteLine($"The bitwise AND result is {a << b} in binary: { Convert.ToString((a << b), 2)}");
            Console.WriteLine("Bitwise >>");
            Console.WriteLine($"The bitwise AND result is {a >> b} in binary: { Convert.ToString((a >> b), 2)}");
            Console.ReadKey();
        }

    }
}
    

Executing the code gives us the following result.

      The value of a is 6 in binary: 110, b is 17 in binary: 10001!
Bitwise OR
The bitwise OR result is 23 in binary: 10111
Bitwise AND
The bitwise AND result is 0 in binary: 0
Bitwise Complement
The bitwise AND result is -7 in binary: 11111111111111111111111111111001
Bitwise XOR
The bitwise AND result is 23 in binary: 10111
Bitwise <<
The bitwise AND result is 786432 in binary: 11000000000000000000
Bitwise >>
The bitwise AND result is 0 in binary: 0
    

Conclusion

These two categories of operators in C# may be the hardest to grasp because they go against the dogma of the decimal number system taught to us in school. Entire careers can be built without utilizing any of these operators based on special circumstances, but it's still good to clarify these concepts in your head. With time, it becomes obvious that behind the scenes of each and every application, these types of manipulations are happening—we just have a pretty good abstraction layer that helps us overcome the binary system.

I hope this has been informative for you and I would like to thank you for reading it!