There is a concept in C# and many other programming languages called overloading. This is a technique for implementing polymorphism, an object-oriented programming paradigm. By definition, polymorphism means you can have multiple interchangeable classes that implement methods and properties differently. This concept applies to functions as well. You can define them in different forms, which are adjusted to different situations that your application needs to handle. A common example is a method with the same name but different parameter list.
Some important things to know about overloading:
We will start with method overloads, then turn our sights towards operator overloads.
Why do we need overloading in C#? We may need a class that reacts a bit differently to different numbers of arguments passed to its methods, but we don't want to have different names for the method for each situation.
There are three distinct ways to overload a method:
Let's demonstrate with an example class.
1using System;
2
3namespace Overloader
4{
5 class Mathher
6 {
7
8 public int Multiply(int a, int b)
9 {
10 return (a * b);
11 }
12 public string Multiply(int a, string b)
13 {
14 string result="";
15 for (int i = 0; i < a; i++)
16 {
17 result = result + b;
18 }
19 return result;
20 }
21 public string Multiply(string a, int b)
22 {
23 string result = "";
24 for (int i = 0; i < b; i++)
25 {
26 result = result + a;
27 }
28 return result;
29 }
30 static void Main(string[] args)
31 {
32 Mathher m = new Mathher();
33 int a = 10;
34 int b = 20;
35 Console.WriteLine($"Calling the Multiply function with two integers -> int({nameof(a)}):{a}, and int({b}):{b}");
36 Console.WriteLine($"Result: {m.Multiply(a, b)}");
37 int c = 15;
38 string d = "P";
39 Console.WriteLine($"Calling the Multiply function with one integer and one string -> int({nameof(c)}):{c}, and str({d}):{d}");
40 Console.WriteLine($"Result: {m.Multiply(c, d)}");
41 int e = 9;
42 string f = "K";
43 Console.WriteLine($"Calling the Multiply function with one string and one integer -> str({nameof(e)}):{e}, and int({f}):{f}");
44 Console.WriteLine($"Result: {m.Multiply(e, f)}");
45 Console.ReadKey(); ;
46 }
47 }
48}
In this class I demonstrated the three distinct ways to overload a method of my class. The first signature returns an integer from two input integers, which is the product of their multiplication. The second signature takes an integer and a string and repeats the string integer-number of times. The third one is needed to complete the circle, meaning we can call the method with a string and an integer as arguments and it also produces the string integer-number of times.
1Calling the Multiply function with two integers -> int(a):10, and int(20):20
2Result: 200
3Calling the Multiply function with one integer and one string -> int(c):15, and str(P):P
4Result: PPPPPPPPPPPPPPP
5Calling the Multiply function with one string and one integer -> str(e):9, and int(K):K
6Result: KKKKKKKKK
C# provides operators that are supported by the built-in types. There are many types of operators, and probably the most common one is the arithmetic operator, which you are already familiar with. Operators have precedence that defines the order in which they are evaluated, and they have strict rules too. If you are interested in learning more about the importance of order, read my corresponding guide. The reason developers usually add operators to their custom types or classes is to provide compatibility with the operators that already work with built-in types. The other reason is that you may want to provide similar functionality to those built-in operators. This is a very detailed cover about the operators you are able to overload.
Imagine, if you will, that you would like to create a little mathematical application that produces the total surface of two triangles in 2D space.
You could construct your class with the following definition to add two triangles with instance methods.
1Triangle tri1 = new Triangle(2,3,4);
2Triangle tri1 = new Triangle(10,15,20);
3
4Triangle result = tri1.Add(tri2);
You could implement the solution with static methods as well.
1Triangle tri1 = new Triangle(2,3,4);
2Triangle tri1 = new Triangle(10,15,20);
3
4Triangle result = Triangle.Add(tri1,tri2);
Let's make this look more professional and try to overload our operator to harness the power of the C# capability.
1Triangle tri1 = new Triangle(2,3,4);
2Triangle tri1 = new Triangle(10,15,20);
3
4Triangle result = tri1 + tri2;
Let's create our class, which supports the above. We need two constructors with different signatures, and we need to override the +
operator to achieve this. There is a simple formula to help you calculate the surface of the triangle: T = (a * ma) / 2. This is the length of one side multiplied by the shortest distance between that side and the intersection of the two other sides, then divided by 2.
1using System;
2
3namespace Overloader
4{
5 public class Triangle
6 {
7 public int a;
8 public int ma;
9 public double surface;
10 public Triangle(int a, int ma)
11 {
12 this.a = a;
13 this.ma = ma;
14 this.surface = (a * ma) / 2;
15 }
16 public Triangle(double surface)
17 { this.surface = surface; }
18 public static Triangle operator +(Triangle tri1, Triangle tri2)
19 {
20 Triangle result = new Triangle((tri1.surface + tri2.surface));
21 return result;
22 }
23 }
24
25 class Mainer
26 {
27 static void Main(string[] args)
28 {
29 Triangle tri1 = new Triangle(8, 12);
30 Console.WriteLine($"The first triangle: {nameof(tri1)} with surface is:{tri1.surface}");
31 Triangle tri2 = new Triangle(14, 16);
32 Console.WriteLine($"The second triangle: {nameof(tri2)} with surface is:{tri2.surface}");
33 Triangle tri3 = tri1 + tri2;
34 Console.WriteLine($"The third triangle: {nameof(tri3)} with surface is:{tri3.surface} is the product of {nameof(tri1)} and {nameof(tri2)}");
35 Console.ReadKey(); ;
36 }
37 }
38}
In our operator override, we simply return a new instance, which is created with the constructor that takes one and only one argument, which is the surface.
Calling the class will produce the following result.
1The first triangle: tri1 with surface is:48
2The second triangle: tri2 with surface is:112
3The third triangle: tri3 with surface is:160 is the product of tri1 and tri2
The nameof
operator is only used to print the name of the variables dynamically. It takes an object and it returns a string with its name.
Overloading has two distinct categories. One is for class methods, and the other is for operators. Both are very straightforward concepts which are easy to grasp and bring new functionality to your application. In this guide, we learned how to overload methods and extend our class with unique functionality, then we revisited the idea and overloaded a built-in operator that allows us to calculate the total sum of the surface of two triangles. I hope this was informative for you and you found what you were looking for. Thank you for reading.