All unary and
binary operators have pre-defined implementations, that are
automatically available in any expressions. In addition to this
pre-defined implementations, user defined implementations can also be
introduced in C#. The mechanism of giving a special meaning to a
standard C# operator with respect to a user defined data type such as
classes or structures is known as operator overloading. Remember that it
is not possible to overload all operators in C#. The following table
shows the operators and their overloadability in C#.
In
C#, a special function called operator function is used for overloading
purpose. These special function or method must be public and static.
They can take only value arguments. The ref and out parameters are not
allowed as arguments to operator functions. The general form of an
operator function is as follows.
public static return_type operator op (argument list)
Where the op is the operator to be overloaded and operator is the required keyword. For overloading the unary operators, there is only one argument and for overloading a binary operator there are two arguments. Remember that at least one of the arguments must be a user-defined type such as class or struct type.
Overloading Unary Operators
The general form of operator function for unary operators is as follows.
public static return_type operator op (Type t)
{
// Statements
}
Where Type must be a class or struct.
The return type can be any type except void for unary operators like +, ~, ! and dot (.) but the return type must be the type of 'Type' for ++ and - operators and must be a bool type for true and false operators. Also remember that the true and false operators can be overloaded only as pairs. The compilation error occurs if a class declares one of these operators without declaring the other.
The following program overloads the unary - operator inside the class Complex
// Unary operator overloading
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
public static Complex operator -(Complex c)
{
Complex temp = new Complex();
temp.x = -c.x;
temp.y = -c.y;
return temp;
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex();
c2.ShowXY(); // displays 0 & 0
c2 = -c1;
c2.ShowXY(); // diapls -10 & -20
}
}
Overloading Binary Operators An overloaded binary operator must take two arguments; at least one of them must be of the type class or struct, in which the operation is defined. But overloaded binary operators can return any value except the type void. The general form of a overloaded binary operator is as follows.
public static return_type operator op (Type1 t1, Type2 t2)
{
//Statements
}
//A concrete example is given below.
// Binary operator overloading
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex() { }
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
public static Complex operator +(Complex c1, Complex c2)
{
Complex temp = new Complex();
temp.x = c1.x + c2.x;
temp.y = c1.y + c2.y;
return temp;
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex(20, 30);
c2.ShowXY(); // displays 20 & 30
Complex c3 = new Complex();
c3 = c1 + c2;
c3.ShowXY(); // dislplays 30 & 50
}
}
The binary operators such as = =, ! =, <, >, < =, > = can be overloaded only as pairs. Remember that when a binary arithmetic operator is overloaded, corresponding assignment operators also get overloaded automatically. For example if we overload + operator, it implicitly overloads the + = operator also.
Operator Overloading & Inheritance
Even though the overloaded operators are declared as static, they are inherited to the derived classes. Because operator declaration always requires the class or struct in which the operator is declared, to participate in the signature of the operator, it is jot possible for an operator declared in a derived class to hide an operator declared in a base class. Thus the new modifier is never required and there never permitted in an operator declaration.
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
public static Complex operator +(Complex c1, Complex c2)
{
Complex temp = new Complex();
temp.x = c1.x + c2.x;
temp.y = c1.y + c2.y;
return temp;
}
}
class MyComplex : Complex
{
private double x;
private double y;
public MyComplex(double i, double j)
{
x = i;
y = j;
}
public MyComplex()
{
}
public new void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
}
class MyClient
{
public static void Main()
{
MyComplex mc1 = new MyComplex(1.5, 2.5);
mc1.ShowXY();
MyComplex mc2 = new MyComplex(3.5, 4.5);
mc2.ShowXY();
MyComplex mc3 = new MyComplex();
//mc3 = mc1 + mc2;
//mc3.ShowXY();
}
}
Overloading Equality Operators
Since all user defined classes, by default, inherit from Syste.object, they inherit the System.object.Equals() method. The default implementation of Equals() method provide a reference based comparison. But it is possible to override this method inside the user-defined class so that they can provide a value-based comparison. The following class is an example for a reference-based comparison of Equals() method.
// Equals() Default Implementation
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex(10, 20);
c2.ShowXY(); // displays 10 & 20
Complex c3 = c2;
c3.ShowXY(); // dislplays 10 & 20
if (c1.Equals(c2))
Console.WriteLine("OK");
else
Console.WriteLine("NOT OK");
if (c2.Equals(c3))
Console.WriteLine("OK1");
}
}
he above program on execution displays "NOT OK" and "OK1". That means the Equals() method by default do a reference comparison. Remember that the values of objects c1 and c2 are same. But they have different references. But in the case of c2 and c3, they refer to the same object on the memory.
But in C#, it is possible to override the Equals() method inside any user defined class as shown below, so that they can do a value-based comparison.
// Equals() Overriding Default Implementation
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
public override bool Equals(object o)
{
if ((Complex)o.x == this.x && (Complex)o.y == this.y)
return true;
else
return false;
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex(10, 20);
c2.ShowXY(); // displays 10 & 20
Complex c3 = c2;
c3.ShowXY(); // dislplays 10 & 20
if (c1.Equals(c2))
Console.WriteLine("OK");
else
Console.WriteLine("NOT OK");
if (c2.Equals(c3))
Console.WriteLine("OK1");
}
}
Now the program displays both "OK" and "OK1" on the command prompt.
Remember that when we override the Equals() method inside a class, we will need to override GetHashCode() method also.
Now let us see how we can override the operator = = and ! = so that they can do the comparisons.
// Overloading = = and ! = operators
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}",x,y);
}
public override bool Equals(object o)
{
if((Complex)o.x == this.x && (Complex)o.y == this.y )
return true;
else
return false;
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
public static bool operator = = (Complex c1, Complex c2)
{
return c1.Equals(c2);
}
public static bool operator ! = (Complex c1, Complex c2)
{
return ! c1.Equals(c2);
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10,20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex(10,20);
c2.ShowXY(); // displays 10 & 20
Complex c3 = c2;
c3.ShowXY(); // dislplays 10 & 20
if(c1 = = c2)
Console.WriteLine("OK");
else if(c2 ! = c3)
Console.WriteLine("OK1");
else
Console.WriteLine("NOT OK");
}
}
nstead of repeating the codes I just call the override Equals() method inside the operator functions. Remember that if we overload the = = operator inside a class or struct we must also override ! = operator.
Summary
The code uses the feature of Operator Overloading in C#. It shows how different operators are overloaded and can be used in a easy manner.
protected void Page_Load(object sender, EventArgs e)
{
Rectangle objRect1 = new Rectangle();
Rectangle objRect2 = new Rectangle();
Rectangle objRect3 = new Rectangle(10, 15);
objRect1.Height = 15;
objRect1.Width = 10;
objRect2.Height = 25;
objRect2.Width = 10;
Console.WriteLine("Rectangle#1 " + objRect1);
Console.WriteLine("Rectangle#2 " + objRect2);
Console.WriteLine("Rectangle#3 " + objRect3);
if (objRect1 == objRect2)
{
Console.WriteLine("Rectangle1 & Rectangle2 are Equal.");
}
else
{
if (objRect1 > objRect2)
{
Console.WriteLine("Rectangle1 is greater than Rectangle2");
}
else
{
Console.WriteLine("Rectangle1 is lesser than Rectangle2");
}
}
if (objRect1 == objRect3)
{
Console.WriteLine("Rectangle1 & Rectangle3 are Equal.");
}
else
{
Console.WriteLine("Rectangle1 & Rectangle3 are not Equal.");
}
}
class Rectangle
{
private int iHeight;
private int iWidth;
public Rectangle()
{
Height = 0;
Width = 0;
}
public Rectangle(int w, int h)
{
Width = w;
Height = h;
}
public int Width
{
get
{
return iWidth;
}
set
{
iWidth = value;
}
}
public int Height
{
get
{
return iHeight;
}
set
{
iHeight = value;
}
}
public int Area
{
get
{
return Height * Width;
}
}
/* OverLoading == */
public static bool operator ==(Rectangle a, Rectangle b)
{
return ((a.Height == b.Height) && (a.Width == b.Width));
}
/* OverLoading != */
public static bool operator !=(Rectangle a, Rectangle b)
{
return !(a == b);
}
/* Overloding > */
public static bool operator >(Rectangle a, Rectangle b)
{
return a.Area > b.Area;
}
/* Overloading < */
public static bool operator <(Rectangle a, Rectangle b)
{
return !(a > b);
}
/* Overloading >= */
public static bool operator >=(Rectangle a, Rectangle b)
{
return (a > b) || (a == b);
}
/* Overloading <= */
public static bool operator <=(Rectangle a, Rectangle b)
{
return (a < b) || (a == b);
}
public override String ToString()
{
return "Height=" + Height + ",Width=" + Width;
}
}
Operators | Overloadability |
+, -, *, /, %, &, |, <<, >> | All C# binary operators can be overloaded. |
+, -, !, ~, ++, --, true, false | All C# unary operators can be overloaded. |
==, !=, <, >, <= , >= | All relational operators can be overloaded, but only as pairs. |
&&, || | They can't be overloaded. |
[] (Array index operator) | They can't be overloaded. |
() (Conversion operator) | They can't be overloaded. |
+=, -=, *=, /=, %= | These compound assignment operators can be overloaded. But in C#, these operators are automatically overloaded when the respective binary operator is overloaded. |
=, . , ?:, ->, new, is, as, sizeof | These operators can't be overloaded in C#. |
public static return_type operator op (argument list)
Where the op is the operator to be overloaded and operator is the required keyword. For overloading the unary operators, there is only one argument and for overloading a binary operator there are two arguments. Remember that at least one of the arguments must be a user-defined type such as class or struct type.
Overloading Unary Operators
The general form of operator function for unary operators is as follows.
public static return_type operator op (Type t)
{
// Statements
}
Where Type must be a class or struct.
The return type can be any type except void for unary operators like +, ~, ! and dot (.) but the return type must be the type of 'Type' for ++ and - operators and must be a bool type for true and false operators. Also remember that the true and false operators can be overloaded only as pairs. The compilation error occurs if a class declares one of these operators without declaring the other.
The following program overloads the unary - operator inside the class Complex
// Unary operator overloading
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
public static Complex operator -(Complex c)
{
Complex temp = new Complex();
temp.x = -c.x;
temp.y = -c.y;
return temp;
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex();
c2.ShowXY(); // displays 0 & 0
c2 = -c1;
c2.ShowXY(); // diapls -10 & -20
}
}
Overloading Binary Operators An overloaded binary operator must take two arguments; at least one of them must be of the type class or struct, in which the operation is defined. But overloaded binary operators can return any value except the type void. The general form of a overloaded binary operator is as follows.
public static return_type operator op (Type1 t1, Type2 t2)
{
//Statements
}
//A concrete example is given below.
// Binary operator overloading
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex() { }
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
public static Complex operator +(Complex c1, Complex c2)
{
Complex temp = new Complex();
temp.x = c1.x + c2.x;
temp.y = c1.y + c2.y;
return temp;
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex(20, 30);
c2.ShowXY(); // displays 20 & 30
Complex c3 = new Complex();
c3 = c1 + c2;
c3.ShowXY(); // dislplays 30 & 50
}
}
The binary operators such as = =, ! =, <, >, < =, > = can be overloaded only as pairs. Remember that when a binary arithmetic operator is overloaded, corresponding assignment operators also get overloaded automatically. For example if we overload + operator, it implicitly overloads the + = operator also.
Operator Overloading & Inheritance
Even though the overloaded operators are declared as static, they are inherited to the derived classes. Because operator declaration always requires the class or struct in which the operator is declared, to participate in the signature of the operator, it is jot possible for an operator declared in a derived class to hide an operator declared in a base class. Thus the new modifier is never required and there never permitted in an operator declaration.
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
public static Complex operator +(Complex c1, Complex c2)
{
Complex temp = new Complex();
temp.x = c1.x + c2.x;
temp.y = c1.y + c2.y;
return temp;
}
}
class MyComplex : Complex
{
private double x;
private double y;
public MyComplex(double i, double j)
{
x = i;
y = j;
}
public MyComplex()
{
}
public new void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
}
class MyClient
{
public static void Main()
{
MyComplex mc1 = new MyComplex(1.5, 2.5);
mc1.ShowXY();
MyComplex mc2 = new MyComplex(3.5, 4.5);
mc2.ShowXY();
MyComplex mc3 = new MyComplex();
//mc3 = mc1 + mc2;
//mc3.ShowXY();
}
}
Overloading Equality Operators
Since all user defined classes, by default, inherit from Syste.object, they inherit the System.object.Equals() method. The default implementation of Equals() method provide a reference based comparison. But it is possible to override this method inside the user-defined class so that they can provide a value-based comparison. The following class is an example for a reference-based comparison of Equals() method.
// Equals() Default Implementation
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex(10, 20);
c2.ShowXY(); // displays 10 & 20
Complex c3 = c2;
c3.ShowXY(); // dislplays 10 & 20
if (c1.Equals(c2))
Console.WriteLine("OK");
else
Console.WriteLine("NOT OK");
if (c2.Equals(c3))
Console.WriteLine("OK1");
}
}
he above program on execution displays "NOT OK" and "OK1". That means the Equals() method by default do a reference comparison. Remember that the values of objects c1 and c2 are same. But they have different references. But in the case of c2 and c3, they refer to the same object on the memory.
But in C#, it is possible to override the Equals() method inside any user defined class as shown below, so that they can do a value-based comparison.
// Equals() Overriding Default Implementation
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
public override bool Equals(object o)
{
if ((Complex)o.x == this.x && (Complex)o.y == this.y)
return true;
else
return false;
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex(10, 20);
c2.ShowXY(); // displays 10 & 20
Complex c3 = c2;
c3.ShowXY(); // dislplays 10 & 20
if (c1.Equals(c2))
Console.WriteLine("OK");
else
Console.WriteLine("NOT OK");
if (c2.Equals(c3))
Console.WriteLine("OK1");
}
}
Now the program displays both "OK" and "OK1" on the command prompt.
Remember that when we override the Equals() method inside a class, we will need to override GetHashCode() method also.
Now let us see how we can override the operator = = and ! = so that they can do the comparisons.
// Overloading = = and ! = operators
// Author: murlid05@gmail.com
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}",x,y);
}
public override bool Equals(object o)
{
if((Complex)o.x == this.x && (Complex)o.y == this.y )
return true;
else
return false;
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
public static bool operator = = (Complex c1, Complex c2)
{
return c1.Equals(c2);
}
public static bool operator ! = (Complex c1, Complex c2)
{
return ! c1.Equals(c2);
}
}
class MyClient
{
public static void Main()
{
Complex c1 = new Complex(10,20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex(10,20);
c2.ShowXY(); // displays 10 & 20
Complex c3 = c2;
c3.ShowXY(); // dislplays 10 & 20
if(c1 = = c2)
Console.WriteLine("OK");
else if(c2 ! = c3)
Console.WriteLine("OK1");
else
Console.WriteLine("NOT OK");
}
}
nstead of repeating the codes I just call the override Equals() method inside the operator functions. Remember that if we overload the = = operator inside a class or struct we must also override ! = operator.
Summary
- The
user defined operator declarations can't modify the syntax, precedence
or associatively of an operator. For example, a + operator is always a
binary operator having a predefined precedence and an associatively of
left to right.
- User defined operator implementations are given preference over predefined implementations.
- Operator overload methods can't return void.
- The
operator overload methods can be overloaded just like any other methods
in C#. The overloaded methods should differ in their type of arguments
and/or number of arguments and/or order of arguments. Remember that in
this case also the return type is not considered as part of the method
signature.
- emember that the capability to overload operators is not a requirement of the common language specification. Hence, not all .NET aware languages supports operator overloading.
The code uses the feature of Operator Overloading in C#. It shows how different operators are overloaded and can be used in a easy manner.
protected void Page_Load(object sender, EventArgs e)
{
Rectangle objRect1 = new Rectangle();
Rectangle objRect2 = new Rectangle();
Rectangle objRect3 = new Rectangle(10, 15);
objRect1.Height = 15;
objRect1.Width = 10;
objRect2.Height = 25;
objRect2.Width = 10;
Console.WriteLine("Rectangle#1 " + objRect1);
Console.WriteLine("Rectangle#2 " + objRect2);
Console.WriteLine("Rectangle#3 " + objRect3);
if (objRect1 == objRect2)
{
Console.WriteLine("Rectangle1 & Rectangle2 are Equal.");
}
else
{
if (objRect1 > objRect2)
{
Console.WriteLine("Rectangle1 is greater than Rectangle2");
}
else
{
Console.WriteLine("Rectangle1 is lesser than Rectangle2");
}
}
if (objRect1 == objRect3)
{
Console.WriteLine("Rectangle1 & Rectangle3 are Equal.");
}
else
{
Console.WriteLine("Rectangle1 & Rectangle3 are not Equal.");
}
}
class Rectangle
{
private int iHeight;
private int iWidth;
public Rectangle()
{
Height = 0;
Width = 0;
}
public Rectangle(int w, int h)
{
Width = w;
Height = h;
}
public int Width
{
get
{
return iWidth;
}
set
{
iWidth = value;
}
}
public int Height
{
get
{
return iHeight;
}
set
{
iHeight = value;
}
}
public int Area
{
get
{
return Height * Width;
}
}
/* OverLoading == */
public static bool operator ==(Rectangle a, Rectangle b)
{
return ((a.Height == b.Height) && (a.Width == b.Width));
}
/* OverLoading != */
public static bool operator !=(Rectangle a, Rectangle b)
{
return !(a == b);
}
/* Overloding > */
public static bool operator >(Rectangle a, Rectangle b)
{
return a.Area > b.Area;
}
/* Overloading < */
public static bool operator <(Rectangle a, Rectangle b)
{
return !(a > b);
}
/* Overloading >= */
public static bool operator >=(Rectangle a, Rectangle b)
{
return (a > b) || (a == b);
}
/* Overloading <= */
public static bool operator <=(Rectangle a, Rectangle b)
{
return (a < b) || (a == b);
}
public override String ToString()
{
return "Height=" + Height + ",Width=" + Width;
}
}
No comments:
Post a Comment