Author : Rahul
Last Modified : 14-May-2021
Complexity : Beginner

Operator Overloading in C#


Introduction

Suppose we have one class named Complex Number and we want to implement arithmetic operation on this class. There is two way to do this:

  1. By creating Add, Subtract, Multiplication, Division function which will do required operation.

  2. By overloading arithmetic operator(+,-,*,/), so that if we write num1 + num2 and it will add two Complex Number just like primitive type. This is done through Operator Overloading.

Operator Overloading

Operator Overloading provides a way of implementing arithmetic operation on custom type just like primitive type.

Syntax

access_specifier  return_type  operator Operator_symbol (parameter_list)
{
    // Code block
}

Description​​​

  • access_specifier: It can be public, private, protected or internal.
  • return_type: Type of the data which will return after performing the operation. It can be any valid C# data type.
  • operator: It is a keyword.
  • Operator_symbol: The symbol which needs to be overload.
  • parameter_list: The list of parameters that are operand for operator symbol.

Example

// C# program to define overloading of the binary operator
using System;
 
  class TestNumber
  {

    public int num;

    // Constructor
    public TestNumber(int n)
    {
      num = n;
    }

    public TestNumber()
    {
    }

    //Overloading + operator
    public static TestNumber operator +(TestNumber num1, TestNumber num2)
    {
      TestNumber number = new TestNumber();
      number.num = num1.num + num2.num;
      return number;
    }
  }

  class OperatorMain
  {
    public static void Main()
    {

      TestNumber num1 = new TestNumber(3);
      TestNumber num2 = new TestNumber(4);
      TestNumber number = num1 + num2;

      Console.Write("Result Test Number:\n");
      Console.WriteLine("Number = {0}", number.num);
    }
  }

Output

Result Test Number:
Number = 7

 

Advantage

The main advantage of Operator Overloading is that, by using it, the code is easily readable as we write obj1 + obj2 to add two objects.

The below table describes which operator can be overloaded and which can not:

Operators Description
+, -, !, ~, ++, – – Unary operator can be overloaded and they take one operand.
+, -, *, /, % Binary operator can be overloaded and they take two operands.
==, !=, = Comparison operator can be overloaded and they take two operands.
&&, || Conditional logical operators can not be overloaded.
+=, -+, *=, /=, %=, = Assignment operator can not be overloaded.

 

Overloading the Unary operators

To overload the unary operator, the operator function takes only one argument and return the object of the containing type. Below code is used to understand the overloading of the unary operator:

// C# program to define overloading of unary operator
using System;
 
  class ComplexNumber
  {
    public int real;
    public int img;

    // Constructor
    public ComplexNumber(int r, int i)
    {
      real = r;
      img = i;
    }

    public ComplexNumber()
    {
    }

    public double Value
    {
      get
      {
        return Math.Sqrt(real * real + img * img);
      }
    }

    //Overloading ++ operator
    public static ComplexNumber operator ++(ComplexNumber num1)
    {
      num1 += 1;
      return num1;
    }

    //Overloading + operator
    public static ComplexNumber operator +(ComplexNumber num1, int val)
    {
      ComplexNumber num = new ComplexNumber();
      num.real = num1.real + val;
      num.img = num1.img + val;
      return num;
    }

    //Overloading + operator
    public static ComplexNumber operator +(int val, ComplexNumber num1)
    {
      return num1 + val;
    }
  }

  class OperatorMain
  {
    public static void Main()
    {
      ComplexNumber num1 = new ComplexNumber(3, 5);
      ComplexNumber result = new ComplexNumber();
      //Pre Increment
      result = num1++;
      Console.Write("Result (Pre Increment) Complex Number:\n");
      Console.WriteLine("Real Part = {0}", result.real);
      Console.WriteLine("Imaginary Part = {0}", result.img);
      Console.WriteLine("Value = {0}\n", result.Value);

      //Post Increment
      result = ++num1;
      Console.Write("Result (Post Increment) Complex Number:\n");
      Console.WriteLine("Real Part = {0}", result.real);
      Console.WriteLine("Imaginary Part = {0}", result.img);
      Console.WriteLine("Value = {0}", result.Value);
    }
  }

Output

Result (Pre Increment) Complex Number:
Real Part =  4
Imaginary Part =  6
Value = 7.21
Result (Post Increment) Complex Number:
Real Part =  4
Imaginary Part =  6
Value = 7.21

 

Overloading the Binary operators

To overload binary operator, operator function takes two arguments and return the object of the containing type. The two arguments maybe both are object type or one is an object type and the other is a number type. Below code is used to understand the overloading binary operator:

Overloading Binary operator with both arguments is of object type (obj1 + obj2)

// C# program to define overloading of the binary operator
using System;
 
  class ComplexNumber
  {
    public int real;
    public int img;


    // Constructor
    public ComplexNumber(int r, int i)
    {
      real = r;
      img = i;
    }

    public ComplexNumber()
    {
    }

    public double Value
    {
      get
      {
        return Math.Sqrt(real * real + img * img);
      }
    }

    //Overloading + operator
    public static ComplexNumber operator +(ComplexNumber num1, ComplexNumber num2)
    {
      ComplexNumber num = new ComplexNumber();
      num.real = num1.real + num2.real;
      num.img = num1.img + num2.img;
      return num;
    }
  }

  class OperatorMain
  {
    public static void Main()
    {
      ComplexNumber num1 = new ComplexNumber(3, 5);
      ComplexNumber num2 = new ComplexNumber(4, 7);
      ComplexNumber num = num1 + num2;

      Console.Write("Result Complex Number:\n");
      Console.WriteLine("Real Part = {0}", num.real);
      Console.WriteLine("Imaginary Part = {0}", num.img);
      Console.WriteLine("Value = {0}", num.Value);
    }
  }

Output

Result Complex Number:
Real Part =  7
Imaginary Part =  12
Value = 13.89

Overloading Binary operator with the argument is of object type and another argument is of number type (obj1 + 1 or 1 + obj1)

// C# program to define overloading of the binary operator
using System;
 
  class ComplexNumber
  {
    public int real;
    public int img;

    // Constructor
    public ComplexNumber(int r, int i)
    {
      real = r;
      img = i;
    }

    public ComplexNumber()
    {
    }

    public double Value
    {
      get
      {
        return Math.Sqrt(real * real + img * img);
      }
    }

    //Overloading + operator
    public static ComplexNumber operator +(ComplexNumber num1, int val)
    {
      ComplexNumber num = new ComplexNumber();
      num.real = num1.real + val;
      num.img = num1.img + val;
      return num;
    }

    //Overloading + operator
    public static ComplexNumber operator +(int val, ComplexNumber num1)
    {
      return num1 + val;
    }
  }

  class OperatorMain
  {
    public static void Main()
    {

      ComplexNumber num1 = new ComplexNumber(3, 5);
      ComplexNumber numResult1 = num1 + 5;
      ComplexNumber numResult2 = 7 + num1;

      Console.Write("Result 1 Complex Number:\n");
      Console.WriteLine("Real Part = {0}", numResult1.real);
      Console.WriteLine("Imaginary Part = {0}", numResult1.img);
      Console.WriteLine("Value = {0}\n", numResult1.Value);

      Console.Write("Result 2 Complex Number:\n");
      Console.WriteLine("Real Part = {0}", numResult2.real);
      Console.WriteLine("Imaginary Part = {0}", numResult2.img);
      Console.WriteLine("Value = {0}", numResult2.Value);
    }
  }

Output

Result 1 Complex Number:
Real Part =  8
Imaginary Part =  10
Value = 12.81

Result 2 Complex Number:
Real Part =  10
Imaginary Part =  12
Value = 15.62

 

Overloading the Relational operators

To overload relational operator, operator function take two arguments and return a boolean value. The main thing to remember while overloading relational operator is that relational operator needs to overload in pair meaning that if we want to overload '<' then we also overload '>'. Similarly for '==' and '!='. Below code is used to understand overloading relational operator.

// C# program to define overloading of the relational operator
using System;
 
  class ComplexNumber
  {
    public int real;
    public int img;

    // Constructor
    public ComplexNumber(int r, int i)
    {
      real = r;
      img = i;
    }

    public ComplexNumber()
    {
    }

    public double Value
    {
      get
      {
        return Math.Sqrt(real * real + img * img);
      }
    }

    //Overloading < operator
    public static bool operator <(ComplexNumber num1, ComplexNumber num2)
    {
      return num1.Value < num2.Value;
    }

    //Overloading > operator
    public static bool operator >(ComplexNumber num1, ComplexNumber num2)
    {
      return num1.Value > num2.Value;
    }
  }

  class OperatorMain
  {
    public static void Main()
    {
      ComplexNumber num1 = new ComplexNumber(3, 4);
      ComplexNumber num2 = new ComplexNumber(3, 5);
      bool IsNum1Small = num1 < num2;

      if (IsNum1Small)
      {
        Console.Write("Number 1 is smaller.");
      }
      else
      {
        Console.Write("Number2 is smaller.");
      }
    }
  }

Output

Number 1 is smaller.

If we want to overload == operator then we also overload !=. We also need to override Equals() and GetHashCode() functions so that if result is true for == then result also true for Equals() function and return same value from GetHashCode() function.

// C# program to define overloading of relational operator
using System;
 
class ComplexNumber
  {
    public int real;
    public int img;

    // Constructor
    public ComplexNumber(int r, int i)
    {
      real = r;
      img = i;
    }

    public ComplexNumber()
    {
    }

    public double Value
    {
      get
      {
        return Math.Sqrt(real * real + img * img);
      }
    }

    //Overloading == operator
    public static bool operator ==(ComplexNumber num1, ComplexNumber num2)
    {
      return num1.Value == num2.Value;
    }

    //Overloading != operator
    public static bool operator !=(ComplexNumber num1, ComplexNumber num2)
    {
      return num1.Value != num2.Value;
    }

    public override bool Equals(object obj)
    {
      ComplexNumber r = obj as ComplexNumber;
      if (r != null)
      {
        return r == this;
      }
      return false;
    }

    public override int GetHashCode()
    {
      return Value.GetHashCode();
    }
  }

  class OperatorMain
  {
    public static void Main()
    {
      ComplexNumber num1 = new ComplexNumber(3, 4);
      ComplexNumber num2 = new ComplexNumber(3, 4);
      bool IsNumEqual = num1 == num2;

      if (IsNumEqual)
      {
        Console.Write("Both numbers are equal.");
      }
      else
      {
        Console.Write("Both numbers are not equal.");
      }
    }
  }

Output

Both numbers are equal.

 

Overloading the Conversion operators

We can also implement a conversion operator so that one type can be converted to another type and vice versa. There is two types of conversion as follow:

  1. Implicit Conversion
  2. Explicit Conversion

Implicit Conversion

In this case, we will not explicitly typecast source type to target type. Below code is used to understand overloading implicit conversion:

// C# program to define overloading of implicit conversion
using System;
 
  class ComplexNumber
  {
    public int real;
    public int img;

    // Constructor
    public ComplexNumber(int r, int i)
    {
      real = r;
      img = i;
    }

    public ComplexNumber()
    {
    }

    public double Value
    {
      get
      {
        return Math.Sqrt(real * real + img * img);
      }
    }

    //Overloading implicit conversion
    public static implicit operator ComplexNumber(int i)
    {
      ComplexNumber number = new ComplexNumber(i, 0);
      return number;
    }
  }

  class OperatorMain
  {
    public static void Main()
    {
      ComplexNumber number = 5;

      Console.Write("Result Complex Number:\n");
      Console.WriteLine("Real Part = {0}", number.real);
      Console.WriteLine("Imaginary Part = {0}", number.img);
      Console.WriteLine("Value = {0}", number.Value);
    }
  }

Output

Result Complex Number:
Real Part =  5
Imaginary Part =  0
Value = 5

 

Explicit Conversion

In this case, we will explicitly cast source type to target type. Below code is used to understand overloading explicit conversion.

// C# program to define overloading of explicit conversion
using System;
 
  class ComplexNumber
  {
    public int real;
    public int img;

    // Constructor
    public ComplexNumber(int r, int i)
    {
      real = r;
      img = i;
    }

    public ComplexNumber()
    {
    }

    public double Value
    {
      get
      {
        return Math.Sqrt(real * real + img * img);
      }
    }

    //Overloading explicit conversion
    public static explicit operator double(ComplexNumber number)
    {
      return Math.Sqrt(number.real * number.real + number.img * number.img);
    }
  }

  class OperatorMain
  {
    public static void Main()
    {
      ComplexNumber number = new ComplexNumber(3, 4);
      double value = (double)number;

      Console.Write("Result Complex Number:\n");
      Console.WriteLine("Value = {0}", value);
    }
  }

Output

Result Complex Number:
Value = 5