C#. Overloading binary operators

Overloading binary operators. Operator overloading +, , *, /, %. Nesting arbitrary logic on overload

Before studying this topic, it is recommended that you familiarize yourself with the following topic:


Contents


Search other resources:

1. Features of overloading binary operators

C# allows you to overload the following binary operators:

  • + – addition (a + b);
  • – substraction (a – b);
  • * – multiplication (a * b);
  • / – division (a / b);
  • % – the operator for taking the remainder of division. Can be overloaded at its own discretion;
  • & – bitwise logical “AND”;
  • | – bitwise logical “OR”;
  • ^ – bitwise addition modulo 2;
  • <, > – comparison operators (less than, greater than). In a class, these operators are necessarily overloaded by a pair (both);
  • <=, >= – comparison operators (less than or equal, greater than or equal). These operators are overloaded as a pair;
  • ==, != – comparison operators (equal, not equal). Overloaded by a pair in class.

When overloading binary operators, a static method is created that takes 2 parameters. The type of these parameters is the type of the class that implements the method that overloads the operator.

In the most general case, the overload of a binary operator in a class named ClassName is of the form:

class ClassName
{
  public static ClassName operator op(ClassName obj1, ClassName obj2)
  {
    // Actions to be taken when calling obj1 op obj2
    // ...
  }
}

here

  • op – one of the standard binary operators that can be overloaded (+, -, ==, >, etc.);
  • obj1 – an instance located to the left of the op operator;
  • obj2 – the instance to the right of the op operator.

After overloading, instances of obj1 and obj2 can be combined with the op operator in a more visual way

obj1 op obj2

For example, if you overload the + operator, then the corresponding method call will be

obj1 + obj2

 

2. Overloading of binary operators +, , *, /. Example

A Complex class is specified that defines a complex number. The class contains the minimum possible set of methods and properties for full functioning.

The Complex class redefines the +, -, *, / operators, which implement respectively addition, subtraction, multiplication, and division of two complex numbers.

using System;

namespace ConsoleApp6
{
  class Complex
  {
    // Internal class fields
    private double re, im;

    // Constructor
    public Complex(double re, double im)
    {
      this.re = re;
      this.im = im;
    }

    // Internal field access properties
    public double Re
    {
      get { return re; }
      set { re = value; }
    }

    public double Im
    {
      get { return im; }
      set { im = value; }
    }

    // The operator method, which overloads the binary operator '+',
    // implements the addition of complex numbers.
    public static Complex operator+(Complex cm1, Complex cm2)
    {
      return new Complex(cm1.re + cm2.re, cm1.im + cm2.im);
    }

    // Operator method overloading binary operator '-',
    // implements subtraction of complex numbers
    public static Complex operator-(Complex cm1, Complex cm2)
    {
      return new Complex(cm1.re - cm2.re, cm1.im - cm2.im);
    }

    // Method overloading the '*' operator,
    // implements multiplication of complex numbers
    public static Complex operator*(Complex cm1, Complex cm2)
    {
      return new Complex(cm1.re * cm2.re - cm1.im * cm2.im, 
        cm1.re * cm2.im + cm1.im * cm2.re);
    }

    // Operator overload '/' - division of complex numbers
    public static Complex operator/(Complex cm1, Complex cm2)
    {
      double denom = cm2.re * cm2.re + cm2.im * cm2.im;
      return new Complex((cm1.re * cm2.re + cm1.im * cm2.im) / denom,
        (cm1.im * cm2.re - cm1.re * cm2.im) / denom);
    }

    // Method that displays the state of the current instance
    public void Print(string msg)
    {
      Console.Write(msg + " => ");
      Console.Write(re);
      if (im >= 0)
        Console.Write("+");
      Console.WriteLine(im.ToString() + "*j");
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      // 1. Create 2 objects of type Complex
      Complex cm1 = new Complex(3, 5);
      Complex cm2 = new Complex(2, -4);

      // 2. Display objects
      cm1.Print("cm1");
      cm2.Print("cm2");

      // 3. Add objects
      Complex cm3;
      cm3 = cm1 + cm2; // a method is called that overloads the '+' operator
      cm3.Print("cm1 + cm2");

      // 4. Subtract - calling the Complex.operator-() method
      (cm1 - cm2).Print("cm1-cm2");

      // 5. Multiply
      cm3 = cm1 * cm2;
      cm3.Print("cm1 * cm2");

      // 6. Divide
      cm3 = cm1 / cm2;
      cm3.Print("cm1 / cm2");

      // 7. Usint operators +=, -=, *=, /=
      Complex cm4 = new Complex(1, 1);
      cm4 += cm1; // => cm4 = cm4 + cm1;
      cm4.Print("cm4");

      Complex cm5 = new Complex(2, 3);
      cm5 *= cm2; // => cm5 = cm5 * cm2
      cm5.Print("cm5");

      Console.ReadKey();
    }
  }
}

Result

cm1 => 3+5*j
cm2 => 2-4*j
cm1 + cm2 => 5+1*j
cm1-cm2 => 1+9*j
cm1 * cm2 => 26-2*j
cm1 / cm2 => -0.7+1.1*j
cm4 => 4+6*j
cm5 => 16-2*j

 

3. Features of operator overloading +=, -=, *=, /=, %=

Shorthand assignment operators +=, -=, *=, /=, %= and others like them are considered overloaded as soon as their corresponding operators +,, *, /, % and others are overloaded.

Using the Point class as an example, the + and operators are overloaded. It then shows the invocation of the corresponding +=, -= operators for instances of the Point class.

The overloaded + and operators perform addition and subtraction of point coordinates.

using System;

namespace ConsoleApp6
{
  // A class that describes a point on the coordinate plane
  class Point
  {
    // Internal variables
    private int x, y;

    // Constructor
    public Point(int x, int y)
    {
      this.x = x;
      this.y = y;
    }

    // Coordinate access properties
    public int X
    {
      get { return x; }
    }

    public int Y
    {
      get { return y; }
    }

    // Method that prints the current x, y values
    public void Print(string msg)
    {
      Console.WriteLine(msg + " => " + "( " + x + "; " + y + ")");
    }

    // Overloaded operators '+' та '-'
    public static Point operator+(Point p1, Point p2)
    {
      return new Point(p1.x + p2.x, p1.y + p2.y);
    }

    public static Point operator-(Point p1, Point p2)
    {
      return new Point(p1.x - p2.x, p1.y - p2.y);
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      // 1. Create 2 instances of Point class
      Point pt1 = new Point(3, 8);
      Point pt2 = new Point(4, 9);

      // 2. Use the += operator to calculate the sum of points pt1 and pt2
      pt1 += pt2; // => pt1 = pt1 + pt2; - is performed: pt1 = Point.operator+(pt1, pt2)
      pt1.Print("pt1");

      // 3. Call the operator -= to calculate difference pt2 = pt2 - pt1;
      pt2 -= pt1; // pt2 = Point.operator(pt2, pt1);
      pt2.Print("pt2");

      Console.ReadKey();
    }
  }
}

After overloading the + and operators in the Point class, the corresponding += and -= operators in strings are called in the main() function

pt1 += pt2;
pt2 -= pt1;

After execution, the program produces the following result

pt1 => ( 7; 17)
pt2 => ( -3; -8)

 

4. An example of overloading the % operator. Determining the arithmetic mean of two arrays. Programming arbitrary logic when overloading operators

Methods overloaded by operators can contain code that implements any actions. The code of an overloaded method does not have to match the purpose of the operator that the method overloads.

The % operator defines the remainder of a division of integer values. However, in our case, a different logic is implemented. The arithmetic mean of two operands, which are arrays of the ArrayDouble type, is determined. This example is for demonstration purposes only and shows how the logic of operator methods can be programmed in different ways.

Note that the operator method operator%() returns double, not ArrayDouble.

using System;

namespace ConsoleApp6
{
  // Array of floating point numbers
  class ArrayDouble
  {
    private double[] AD;

    // Constructor
    public ArrayDouble(double[] _AD)
    {
      // Copying AD = _AD
      AD = new double[_AD.Length];
      for (int i = 0; i < AD.Length; i++)
        AD[i] = _AD[i];
    }

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

    // Overloading of operator %.
    // Determination of the arithmetic mean of two operand arrays.
    // Note: the method returns double and not ArrayDouble
    public static double operator%(ArrayDouble AD1, ArrayDouble AD2)
    {
      // 1. Calculate the sum of array elements
      double res = 0;
      for (int i = 0; i < AD1.AD.Length; i++)
        res += AD1.AD[i];
      for (int i = 0; i < AD2.AD.Length; i++)
        res += AD2.AD[i];

      // 2. Return the arithmetic mean
      return res / (AD1.AD.Length + AD2.AD.Length);
    }
  }

  internal class Program
  {
    static void Main(string[] args)
    {
      // 1. Create 2 arrays of double[] type
      double[] A1 = { 2.4, 3.1, 0.8, -2.2, 0.9, 11.6 };
      double[] A2 = { 3.8, 11.7, -4.4, 0.8 };

      // 2. Create 2 instances based on arrays
      ArrayDouble AD1 = new ArrayDouble(A1);
      ArrayDouble AD2 = new ArrayDouble(A2);

      // 3. Print arrays for control
      AD1.Print("AD1");
      AD2.Print("AD2");

      // 4. Use the overloaded % operator to calculate the arithmetic mean.
      double average = AD1 % AD2;
      Console.WriteLine("AD1 % AD2 = {0:f3}", average);

      Console.ReadKey();
    }
  }
}

Result

AD1 => 2.4 3.1 0.8 -2.2 0.9 11.6
AD2 => 3.8 11.7 -4.4 0.8
AD1 % AD2 = 2.850

 


Related topics