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:
-
By creating Add, Subtract, Multiplication, Division function which will do required operation.
-
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:
- Implicit Conversion
- 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