11 Aug, 2007 · 7 minutes read
By default, out of the various C# operators, only the dot operator can be applied to user-defined types. Consider the following code snippet:-
class Program
{
static void Main(string[] args)
{
Car Car1 = new Car();
Car Car2 = new Car();
Car Car3 = Car1 + Car2;
}
}
class Car
{
public int Speed;
public string Name;
}
The compiler generates an error at line 8 saying that the operator + cannot be applied to objects of the Carclass. How is the compiler supposed to know whether we want to add the speeds of two cars or concatenate their names. This is where the concept of Operator Overloading jumps in. Before we see how the + operator is prepared to work with the objects of the Carclass, we need to understand how the concept works. Given below is a code snippet which accomplishes the addition in objects using a specialized method – Add().
using System;
class Program
{
static void Main(string[] args)
{
Car Car1 = new Car();
Car Car2 = new Car();
Car1.Speed = 30;
Car2.Speed = 70;
Car Car3 = Car.Add(Car1, Car2);
Console.WriteLine("Car3's Speed = {0}", Car3.Speed);
Console.Read();
}
}
class Car
{
public int Speed;
public string Name;
public static Car Add(Car Car1, Car Car2)
{
Car NewCar = new Car();
NewCar.Speed = Car1.Speed + Car2.Speed;
return NewCar;
}
}
The Addmethod is declared as static so it can be invoked at the class level as Car.Add(). It takes two parameters of the type Caras inputs. It then creates a new object of the Car class, with a speed equal to the sum of the speeds of the input objects – Car1and Car2. Finally, the new object is returned. In this way, the addition of two objects can be accomplished. The same concept is used in Operator Overloading, except for the fact that the specialized function in their case are of the format operator
Note: The logic inside the Add function is totally up to the the programmer.
using System;
class Program
{
static void Main(string[] args)
{
Car Car1 = new Car();
Car Car2 = new Car();
Car1.Speed = 30;
Car2.Speed = 70;
Car Car3 = Car1 + Car2;
Console.WriteLine("Car3's Speed = {0}", Car3.Speed);
Console.Read();
}
}
class Car
{
public int Speed;
public string Name;
public static Car operator +(Car Car1, Car Car2)
{
Car NewCar = new Car();
NewCar.Speed = Car1.Speed + Car2.Speed;
return NewCar;
}
}
As you can see, the + operator utilizes a function in the background to do its neat work. Although the concept in both the cases is same, using operators allows much greater ease. The code Car Car3 = Car1 + Car2;is much closer to the real world and its easier to type, isn’t it?
Here’s a table showing which operators can/cannot be overloaded in C#.
Operators | Description |
---|---|
+ – ! ~ ++ — | These being unary operators take one operand and can be overloaded. |
+ – * / % | Binary arithmetic operators take two operands and can be overloaded. |
== != < > <= >= | Comparison operators take two parameters and can also be overloaded. |
&& || | These need to be overloaded indirectly using the & and | |
+= -= *= /= %= | Arithmetic assignment operators cannot be overloaded. |
= . ?: -> new is sizeof typeof | These special operators cannot be overloaded. |
Note: The overloading methods must be declared as publicand static.
Below is the logic to accomplish unary – operator overloading. This operator changes the sign of the relative speed and is used as: -
using System;
class Program
{
static void Main(string[] args)
{
Car Car1 = new Car();
Car1.RelativeSpeed = 30;
Car Car2 = -Car1;
}
}
class Car
{
public int RelativeSpeed;
public string Name;
public static Car operator -(Car CarObj)
{
Car NewCar = new Car();
NewCar.RelativeSpeed = -CarObj.RelativeSpeed;
return NewCar;
}
}
Notice, that the overloaded function takes only a single parameter. If another parameter was specified, this function would overload the binary – operator. Structures being user-defined data types can also be overloaded in this fashion. The only difference is that structures being value types, can be implemented in an easier way.
struct Car
{
public int RelativeSpeed;
public string Name;
public static Car operator -(Car CarObj)
{
CarObj.RelativeSpeed = -CarObj.RelativeSpeed;
return CarObj;
}
}
If the same implementation of the Operator – function was used in a class, both Car1and Car2would have the same RelativeSpeed of -30 after line 9. So, in the class implementation we have created a new object of the Car class.
Unlike, C++, C# handles the Pre & Post Increment Operators by itself. Hence, we don’t need to overload them separately. Below is the implementation of the ++ operator in the Carstructure.
using System;
class Program
{
static void Main(string[] args)
{
Car Car1 = new Car();
Car1.RelativeSpeed = 30;
Car Car2 = Car1++;
Car Car3 = ++Car1;
Console.WriteLine("Relative speed of Car1 = {0}, Car2 = {1} and Car3 = {2}"
, Car1.RelativeSpeed, Car2.RelativeSpeed, Car3.RelativeSpeed);
Console.Read();
}
}
struct Car
{
public int RelativeSpeed;
public string Name;
public static Car operator ++(Car CarObj)
{
CarObj.RelativeSpeed++;;
return CarObj;
}
}
At line 9, the overloaded function for the object Car1is invoked. The operation being post increment, Car2gets assigned the current value of Car1which has a relative speed of 30. After this the RelativeSpeedis incremented by 1. So, Car1has a relative speed of 31 now. In the next line, pre increment results in the value of Car1to be incremented by 1 before the value is assigned to Car3. Car1’s RelativeSpeedis now equal to 32. This value gets copied in Car3. So, the output of the code is: Relative speed of Car1 = 32, Car2 = 30 and Car3 = 32.
If the same logic was used in the CarClass’s overloaded function, the output would be: Relative speed of Car1 = 32, Car2 = 32 and Car3 = 32. Why does this happen? As mentioned before, the class is a reference type. Hence, when we say Car1 = Car2, it implies that Car1now points to the same object in the memory as does Car2. In structures, the same statement would be equivalent to Copy the value of Car2in Car1.
Recall that, the Arithmetic Assignment operators ( += -= *= /= %= ) cannot be overloaded. This is because A += Bis equivalent to A = A + B, A -= Bis equivalent to A = A – Band so on. Once, you overload the binary + operator, you can perform the +=operation on the objects of the class. Same is true for the rest of the Arithmetic operators.
Overloading Logical Operators is a bit tricky. Firstly, to overload the && operator the function name should be operator &and for || operator it should be operator |. Secondly, before performing these boolean short-circuit operations, the trueand falseoperators need to be defined.
using System;
class Program
{
static void Main(string[] args)
{
Car Car1 = new Car();
Car Car2 = new Car();
Car1.Running = true;
Car2.Running = false;
Car Car3 = Car1 && Car2;
Console.WriteLine(Car3.Running);
Console.Read();
}
}
class Car
{
public bool Running;
public static Car operator &(Car Car1, Car Car2)
{
Car NewCar = new Car();
NewCar.Running = Car1.Running && Car2.Running;
return NewCar;
}
public static bool operator true(Car CarObj)
{
return true;
}
public static bool operator false(Car CarObj)
{
return false;
}
}