C#. Overloading comparison operators

Overloading comparison operators ==, !=, <, >, <=, >=. Overloading boolean bitwise operators &, |, ^


Contents


Search other resources:

1. Overloading binary comparison operators ==, !=. Example

The comparison operators ==, != can be overloaded in a class. The peculiarity of these operators is that you need to implement both operators at the same time.

The use of binary comparison operators for the ArrayRange class, which implements an array of integers within a given range, is demonstrated. Operators == and != are overloaded in the class. These operators perform an element-by-element comparison of two ArrayRange objects.

It is mandatory to overload these operators in pairs. If the == operator is overloaded, then the != operator must be overloaded.

using System;

namespace ConsoleApp6
{
  class ArrayRange
  {
    // Internal field - array
    private int[] A;
    private int min; // minimum value
    private int max; // maximum value

    // Constructor
    public ArrayRange(int[] _A, int _min, int _max)
    {
      // Set ranges
      if (_min <= _max)
      {
        min = _min; max = _max;
      }

      if (_min >= _max)
      {
        min = _max; max = _min;
      }

      // Make a copy from the original array _A
      A = new int[_A.Length];
      for (int i = 0; i < A.Length; i++)
      {
        if (_A[i] < min)
          A[i] = min;
        else
        if (_A[i] > max)
          A[i] = max;
        else
          A[i] = _A[i];
      }
    }

    // Method that outputs an internal array
    public void Print(string msg)
    {
      Console.WriteLine(msg);
      for (int i = 0; i < A.Length; i++)
        Console.Write(A[i] + " ");
      Console.WriteLine();
      Console.WriteLine("-----------------------------");
    }

    // A method that returns a reference to array A
    public int[] Get() { return A; }

    // Method which overloads the == operator
    public static bool operator==(ArrayRange A1, ArrayRange A2)
    {
      // 1. Length comparison
      if (A1.A.Length != A2.A.Length)
        return false;

      // 2. Element-by-element comparison
      for (int i = 0; i < A1.A.Length; i++)
        if (A1.A[i] != A2.A[i])
          return false;

      return true;
    }

    // Method that overloads the != operator
    public static bool operator!=(ArrayRange A1, ArrayRange A2)
    {
      return !(A1 == A2);
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      // 1. Create arrays of type int[]
      int[] AI1 = { 2, 8, 1, -3, 4 };
      int[] AI2 = { 2, 8, 1, -3, 4 };

      // 2. Create arrays of type ArrayRange
      ArrayRange A1 = new ArrayRange(AI1, 1, 5);
      ArrayRange A2 = new ArrayRange(AI2, 1, 5);

      // 3. Display arrays
      A1.Print("A1");
      A2.Print("A2");

      // 4. Call the overloaded operator == of arrays comparison
      if (A1 == A2)
        Console.WriteLine("A1 == A2");
      else
        Console.WriteLine("A1 != A2");

      // 5. Call another overloaded operator !=
      if (A1 != A2)
        Console.WriteLine("A1 != A2");
      else
        Console.WriteLine("A1 == A2");

      Console.ReadKey();
    }
  }
}

Result

A1
2 5 1 1 4
-----------------------------
A2
2 5 1 1 4
-----------------------------
A1 == A2
A1 == A2

 

2. Overloading of binary comparison operators <, >, <=, >=. Example

Overloading of binary comparison operators >, <, >=, <= must be implemented in pairs. This means that the following pairs of operators must be implemented:

  • > and <;
  • >= and <=.

The example of the Line class demonstrates the overloading of the binary comparison operators >, <, >=, <=. The class methods

operator<()
operator>()
operator>=()
operator<=()

return the result of comparing the lengths of the segments that are the input parameters.

using System;

namespace ConsoleApp6
{
  // A class that describes a line consisting of two points
  class Line
  {
    // Internal variables - segment coordinates
    private double x1, y1, x2, y2;

    // Constructor
    public Line(double x1, double y1, double x2, double y2)
    {
      this.x1 = x1;
      this.y1 = y1;
      this.x2 = x2;
      this.y2 = y2;
    }

    // Access properties
    public double X1 { get { return x1; } }
    public double Y1 { get { return y1; } }
    public double X2 { get { return x2; } }
    public double Y2 { get { return y2; } }

    // Method that outputs line coordinates
    public void Print(string msg)
    {
      Console.Write(msg + "=> ( " + x1 + "; " + y1 + ") - ( " + x2 + "; " + y2 + "), ");
      Console.WriteLine(" length = {0:f2}", Length());
    }

    // Method that returns the length of the segment
    public double Length()
    {
      return Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    // Overloaded methods <, >, <=, >=.
    // In the methods, the lengths of the segments ln1 and ln2 are compared
    public static bool operator>(Line ln1, Line ln2)
    {
      return ln1.Length() > ln2.Length();
    }

    public static bool operator<(Line ln1, Line ln2)
    {
      return !(ln1 > ln2);
    }

    public static bool operator>=(Line ln1, Line ln2)
    {
      return ln1.Length() >= ln2.Length();
    }

    public static bool operator <=(Line ln1, Line ln2)
    {
      return ln1.Length() <= ln2.Length();
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      // 1. Declare 2 segments
      Line ln1 = new Line(1, 1, 2, 4);
      Line ln2 = new Line(3, 5, -1, -7);

      // 2. Display information about segments ln1, ln2
      ln1.Print("ln1");
      ln2.Print("ln2");

      // 3. Compare ln1 < ln2
      if (ln1 < ln2)
        Console.WriteLine("ln1 < ln2");
      else
        Console.WriteLine("ln1 >= ln2");

      // 4. Compare ln1 > ln2
      if (ln1 > ln2)
        Console.WriteLine("ln1 > ln2");
      else
        Console.WriteLine("ln1 <= ln2");

      // 5. Compare ln1 <= ln2
      if (ln1 <= ln2)
        Console.WriteLine("ln1 <= ln2");
      else
        Console.WriteLine("ln1 > ln2");

      // 6. Compare ln1 >= ln2
      if (ln1 >= ln2)
        Console.WriteLine("ln1 >= ln2");
      else
        Console.WriteLine("ln1 < ln2");

      Console.ReadKey();
    }
  }
}

Result

ln1=> ( 1; 1) - ( 2; 4), length = 3.16
ln2=> ( 3; 5) - ( -1; -7), length = 12.65
ln1 < ln2
ln1 <= ln2
ln1 <= ln2
ln1 < ln2

 

3. Overloading of bitwise binary operators & (logical bitwise “AND”), | (logical bitwise “OR”), ^ (modulo 2 addition)

The example shows element-by-element manipulation of arrays consisting of 0 and 1. The ArrayBits class is defined, which declares an array of type byte[].Array elements consist of values 0 and 1. The class overloads the logical bitwise operators &, |, ^.

Methods that overload operators implement the appropriate operations on each element of the array. The operator method operator&() performs bitwise logical “AND” over the elements of two arrays. The operator method operator|() performs bitwise logical “OR” over the elements of arrays. Accordingly, the operator^() method performs bitwise logical addition on each of the elements of the array.

The demo code for the console application is as follows.

using System;

namespace ConsoleApp6
{
  // Class describing the array of bits 0, 1
  class ArrayBits
  {
    private byte[] AB;

    // Constructor
    public ArrayBits(byte[] _AB)
    {
      // Create a new array where non-zero values are 1,
      // and null values are 0
      AB = new byte[_AB.Length];

      for (int i = 0; i < _AB.Length; i++)
        if (_AB[i] != 0)
          AB[i] = 1;
        else
          AB[i] = 0;
    }

    // A method that outputs the internal array AB
    public void Print(string msg)
    {
      Console.Write(msg + " => ");
      for (int i = 0; i < AB.Length; i++)
        Console.Write(AB[i] + " ");
      Console.WriteLine();
    }

    // Overloading of &, |, ^ operators
    // Bitwise "AND"
    public static ArrayBits operator&(ArrayBits AB1, ArrayBits AB2)
    {
      ArrayBits res;

      // Select the array with the smallest length and, based on it,
      // create the resulting array.
      if (AB1.AB.Length<AB2.AB.Length)
      {
        res = new ArrayBits(AB1.AB);
      }
      else
      {
        res = new ArrayBits(AB2.AB);
      }

      // Implement element-wise bitwise "AND"
      // form the resulting array
      for (int i = 0; i < res.AB.Length; i++)
        if ((AB1.AB[i] == 1) && (AB2.AB[i] == 1))
          res.AB[i] = 1;
        else
          res.AB[i] = 0;

      // Return the resulting array
      return res;
    }

    // Bitwise "OR"
    public static ArrayBits operator|(ArrayBits AB1, ArrayBits AB2)
    {
      ArrayBits res;

      // Select the array with the smallest length
      // and create the resulting array based on it.
      if (AB1.AB.Length < AB2.AB.Length)
      {
        res = new ArrayBits(AB1.AB);
      }
      else
      {
        res = new ArrayBits(AB2.AB);
      }

      // Implement element-wise bitwise "OR",
      // form array res
      for (int i = 0; i < res.AB.Length; i++)
        if ((AB1.AB[i] == 0) && (AB2.AB[i] == 0))
          res.AB[i] = 0;
        else
          res.AB[i] = 1;

      // Return the resulting array
      return res;
    }

    // Bitwise modulo 2 addition
    public static ArrayBits operator^(ArrayBits AB1, ArrayBits AB2)
    {
      ArrayBits res;

      // Select the array with the smallest length
      // and create the resulting array based on it.
      if (AB1.AB.Length < AB2.AB.Length)
      {
        res = new ArrayBits(AB1.AB);
      }
      else
      {
        res = new ArrayBits(AB2.AB);
      }

      // Implement element-wise bitwise addition modulo 2, form array res
      for (int i = 0; i < res.AB.Length; i++)
      if (AB1.AB[i] == AB2.AB[i])
        res.AB[i] = 0;
      else
        res.AB[i] = 1;

      // Return the resulting array
      return res;
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      // 1. Create 2 test arrays of type byte[]
      byte[] A1 = { 2, 3, 0, 0, 4, 7, 0, 55 };
      byte[] A2 = { 1, 0, 6, 0, 2, 0, 8, 9, 4, 0, 0 };

      // 2. Create 2 objects based on arrays A1 and A2
      ArrayBits AB1 = new ArrayBits(A1);
      ArrayBits AB2 = new ArrayBits(A2);

      // 3. Print arrays in instances for control
      AB1.Print("AB1 ");
      AB2.Print("AB2 ");

      // 4. Implement bitwise & - AND
      ArrayBits AB3;
      AB3 = AB1 & AB2; // => ArrayBits.operator&(AB1, AB2);
      AB3.Print("AB1 & AB2");

      // 5. Display the result of bitwise | - OR
      (AB1 | AB2).Print("AB1 | AB2"); // => ArrayBits.operator|(AB1, AB2);

       // 6. Implement bitwise ^ - modulo 2 addition
       ArrayBits AB4 = AB1 ^ AB2; // => ArrayBits.operator^(AB1, AB2);
       AB4.Print("AB1 ^ AB2");

       Console.ReadKey();
    }
  }
}

Result

AB1 => 1 1 0 0 1 1 0 1
AB2 => 1 0 1 0 1 0 1 1 1 0 0
AB1 & AB2 => 1 0 0 0 1 0 0 1
AB1 | AB2 => 1 1 1 0 1 1 1 1
AB1 ^ AB2 => 0 1 1 0 0 1 1 0

 

4. Overloading the shift operators <<, >>. Example

In a class, shift operators are overloaded in pairs. This means that if the operator << (shift left) is overloaded, then the operator >> (shift right) must also be overloaded.

using System;

namespace ConsoleApp6
{
  // Array of integers
  class ArrayInt
  {
    private int[] AI;

    // Constructor
    public ArrayInt(int[] _AD)
    {
      // Copy AD = _AD
      AI = new int[_AD.Length];
      for (int i = 0; i < AI.Length; i++)
        AI[i] = _AD[i];
    }

    // A method that outputs an AD array.
    public void Print(string msg)
    {
      Console.Write(msg + " => ");
      for (int i = 0; i < AI.Length; i++)
        Console.Write(AI[i] + " ");
      Console.WriteLine();
    }

    // Overloading of the left shift operator <<
    // The elements of the array are shifted cyclically to the left,
    // The first element of the array replaces the last element.
    // Note: the method returns an instance of type ArrayInt and an integer int
    public static ArrayInt operator<<(ArrayInt AI, int n)
    {
      // 1. Create the instance of array AI
      ArrayInt res = new ArrayInt(AI.AI);

      for (int k = 0; k < n; k++)
      {
        // Shift one position to the left
        int t = res.AI[0];
        for (int i = 0; i < res.AI.Length - 1; i++)
          res.AI[i] = res.AI[i + 1];
        res.AI[AI.AI.Length - 1] = t;
      }

      // 2. Resulting instance
      return res;
    }

    // Operator method overloading right shift operator >>
    public static ArrayInt operator >>(ArrayInt AI, int n)
    {
      // 1. Create an instance of the AI array
      ArrayInt res = new ArrayInt(AI.AI);

      for (int k = 0; k < n; k++)
      {
        // Shift one position to the left
        int t = res.AI[AI.AI.Length - 1];
        for (int i = res.AI.Length - 1; i >= 1; i--)
          res.AI[i] = res.AI[i - 1];
        res.AI[0] = t;
      }

      // 2. Result instance
      return res;
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      // 1. Declare an array of type int[]
      int[] A = { 2, 8, 9, 15, 27 };

      // 2. Create an instance of type ArrayInt
      ArrayInt AI = new ArrayInt(A);
      AI.Print("AI "); // Output array

      // 3. Call left shift operator by 2 positions
      ArrayInt res = AI << 2;
      res.Print("AI << 2");

      // 4. Call the right shift operator by 4 positions
      res = AI >> 4;
      res.Print("AI >> 4");

      Console.ReadKey();
    }
  }
}

Result

AI => 2 8 9 15 27
AI << 2 => 9 15 27 2 8
AI >> 4 => 8 9 15 27 2

 


Related topics