Operator overloading is used to define or overload the built-in operators in a new user-defined class or struct. It looks like a special method with operator keyword and followed by the operator itself. See the following examples.

Example 01-81-01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
```using System;

struct Point
{
int _x;
int _y;

public Point(int x, int y)
{
this._x = x;
this._y = y;
}

public static Point operator +(Point a, Point b)
{
return new Point(a._x + b._x, a._y + b._y);
}

public static Point operator -(Point a, Point b)
{
return new Point(a._x + b._x, a._y + b._y);
}

public override string ToString()
{
return "(" + _x + "," + _y + ")";
}
}

class Test
{
static void Main()
{
Point p1 = new Point(1, 2);
Point p2 = new Point(3, 4);

Console.WriteLine("p1 + p2 = {0}", p1 + p2);
Console.WriteLine("p1 - p2 = {0}", p1 - p2);

}
}
```

Output

```p1 + p2 = (4,6)
p1 - p2 = (-2,-2)
```

Explanation

• Line 14: Define an operator +. 2 parameters indicate + is a binary operator and 2 Point type objects will be added together to return a new Point object.
• Line 19: Define an operator -. It looks like a method.
• Line 37-38: p1+p2 will be calculated in the defined operator + and p1-p2 will be calculated in the operator -.

Unary+, -, !, ~, ++, --, true, falseYestrue and false are a pair and must be defined together.
Binary+, -, *, /, %, &, |, ^, <<, >>Yes2 parameters are needed.
Comparison==, !=, <, >, <=, >=YesOverloaded in pairs. == and != are a pair. So are < and >, <= and >=
Assignment+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=NoBut if + is overloaded the += operator is implicitly overloaded.
Others&&, ||, [], (), =, ., ?:, ->, new, is, sizeof, typeofNoexplicit and implicit can be used to defined new conversion operators.

• An user-defined operator must be declared static and public.
• An user-defined operator implementation always take precedence over its predefined operator implementation.
• If a binary operator is overloaded, the corresponding assignment operator is also implicitly overloaded.
• Unary operators, like ++x or x--, can be overloaded as operator <operator>(x) with one parameter only.
• Binary operators, like + or /, can be overloaded as operator <operator>(x, y) with 2 parameters.
• The syntax, precedence or associativity of an operator can not be changed by any user-defined operator declarations.

Example 01-81-02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
```using System;

class Student
{
string _name;
int _score;

public Student(string name, int score)
{
this._name = name;
this._score = score;
}

public static Student operator +(Student a, Student b)
{
return new Student(a._name + ", " + b._name, a._score + b._score);
}

public static Student operator +(Student a, int more)
{
return new Student(a._name, a._score + more);
}

public static Student operator +(int more, Student a)
{
return new Student(a._name, a._score + more);
}

public static Student operator ++(Student a)
{
return a + 1;
}

public static bool operator ==(Student a, Student b)
{
return a._score == b._score;
}

public static bool operator !=(Student a, Student b)
{
return a._score != b._score;
}

public override string ToString()
{
return "Name: " + _name + " Score: " + _score;
}
}

class Test
{
static void Main()
{
Student s1 = new Student("Mike", 70);
Student s2 = new Student("Steve", 90);

Console.WriteLine(s1);
Console.WriteLine(s2);
Console.WriteLine(s1 + s2);
Console.WriteLine(s1 + 5);
Console.WriteLine(2 + s1);
Console.WriteLine(s1++);
Console.WriteLine(s1);
s1 += 7;
Console.WriteLine(s1);

Student s3 = new Student("Andy", 90);
Console.WriteLine(s2 == s3 ? "s2 == s3" : "s2 != s3");
}
}
```

Output

```Name: Mike Score: 70
Name: Steve Score: 90
Name: Mike, Steve Score: 160
Name: Mike Score: 75
Name: Mike Score: 72
Name: Mike Score: 70
Name: Mike Score: 71
Name: Mike Score: 78
s2 == s3
```

Explanation

• Line 14-27: Operator overloading. each of them has a different signature.
• Line 29-32: The unary ++ operator is defined by calling another operator definition in line 19-22.
• Line 34-42: == and != are redefined together because they are a pair. It is not allowed to define only one of them.
• Line 59-61: + operator implementation is called based on the different parameters and their sequence.
• Line 62-63: ++ operator implementation is called but the reaction of the postfix ++ has never been changed.
• Line 64-65: += operator cannot be overloaded directly but it has been overloaded implicitly.
• Line 67-68: Create a new Student object s3 with the same score in s2. We know both s2 and s3 are reference type and should not be equivalent by default. But the == operator is redefined and takes precedence over its predefined one.

Example 01-81-03

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
```using System;

class IsPositive
{
int _value;
}

class Test
{
static void Main()
{
IsPositive ip = new IsPositive();

if (ip)     // illegal
{
Console.WriteLine("Never Printed");
}

}
}
```

You will get the following error message when trying to run the above example.

```Cannot implicitly convert type 'IsPositive' to 'bool'
```

If it is in C++, the condition of the if statement will return true because the object is initialized and not null. But in C#, the condition must be returned as a boolean type. Thus, true/false operator must be redefined.

Example 01-81-04

The example 01-99-03 is changed as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
```using System;

class IsPositive
{
int _value;

public IsPositive(int value)
{
_value = value;
}

public static bool operator true(IsPositive x){
return x._value > 0;
}

public static bool operator false(IsPositive x)
{
return x._value <= 0;
}

public static bool operator !(IsPositive x)
{
return x ? false : true ;
}
}

class Test
{
static void Main()
{
IsPositive ip = new IsPositive(-5);

if (ip)     // Legal because true/false operators were defined.
{
Console.WriteLine("Positive Nubmer");
}
else
{
Console.WriteLine("Negative Nubmer");
}

if (!ip)     // Legal because true/false operators were defined.
{
Console.WriteLine("Negative Nubmer");
}
else
{
Console.WriteLine("Positive Nubmer");
}

}
}
```

Output

```Negative Nubmer
Negative Nubmer
```

Explanation

• Line 12-19: true and false user-defined Operators are defined as a pair.
• Line 21-24: Define the ! operator. x is evaluated by calling true or false operator function.
• Line 33: true and false user-defined Operator function is called.
• Line 42: ! user-defined Operator function is called.

The () operator cannot be redefined directly. However, an explicit user-defined type conversion operator can be realized by the explicit keyword. also the implicit keyword can be used to declare an implicit user-defined type conversion operator.

Example 01-81-05

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
```using System;

class Number
{
int _value;

public Number(int value)
{
_value = value;
}

public static explicit operator Number(int x){
return new Number(x);
}

public static implicit operator int(Number x)
{
return x._value;
}

public override string ToString()
{
return "Number:" + _value;
}
}

class Test
{
static void Main()
{
int i = 6;
Number n = (Number)i;
Console.WriteLine("{0}", n);

int j = n;
Console.WriteLine("j={0}", j);
}
}
```

Output

```Number:6
j=6
```

Explanation

• Line 12-14: Explicit user-defined type conversion Operator is defined to convert an integer x to Number type by casting.
• Line 16-19: Implicit user-defined type conversion Operator is defined to convert a Number type to an integer implicitly.
• Line 31-32: Test the explicit operator by casting the integer i to a Number object.
• Line 33: The override method ToString() defined in line 21-24 is called implicitly.
• Line 35: Test the implicit operator by converting the Number object n to a new integer j implicitly.