Polymorphism in C#
Tags: csharp, oop
Published: 2022-04-13 02:47:03

Polymorphism is a very important pillar of object-oriented programming, right up there with encapsulation and inheritance. Polymorphism in Greek meaning "many-shaped", this pillar allows for objects to take multiple forms. This sounds more complex than it actually is, so lets dive into some examples.

I have class `A` and class `B`. `B` inherits `A`. In `Main()`, this allows for some interesting behaviour:

```cs
class A { } 

class B : A { }

public class Program
{
	public static void Main(string[] args)
	{
		A a = new B(); //No error?!
 	}
}
```

How is there no error thrown? I am clearly trying to assign an incorrect type to a variable! Except I'm not. When `B` inherits `A`, it becomes a *form* of A, meaning it can be passed along as `A` when needed.

Let's look at some more examples:

```cs
using System;

public class Program
{
	public static void Main(string[] args)
	{
		DoSomething(new A());
 		DoSomething(new B());
	}
	static void DoSomething(A obj)
 	{
 		Console.WriteLine($"Object Type: {obj.GetType()}");
 	}
}
```

Output:

```
Object Type: A
Object Type: B
```

Another example:

```cs
using System;
using System.Collections.Generic;

public class Program
{
	public static void Main(string[] args)
 	{
 		List<A> objs = new List<A>();
 		objs.Add(new A());
 		objs.Add(new B());
 		foreach (A obj in objs)
 		{
 			Console.WriteLine($"Object Type: {obj.GetType()}");
 		}
 	}
}
```

Output:

```
Object Type: A
Object Type: B
```

I know you all are on the edges of your seats, but let me inform you of another *crazy* use of polymorphism: overriding methods. "But isn't that just inheritance?" I hear you ask. And you would be technically correct. Like all pillars of object-oriented programming, inheritance and polymorphism work hand-in-hand to provide you with the best features.

Now the method overriding can be done with two amazing keywords: `virtual` and `override`. `virtual` is essentially the method/field raising its hand to be overridden in a form of the class. `override` is the teacher calling on the method/field to override it in a form of the class.

Let's see these keywords in action:

```cs
using System;

public class Program
{
	public static void Main(string[] args)
 	{
 		DoStuff(new A());
 		DoStuff(new B());
 	}
 	static void DoStuff(A obj)
 	{
 		obj.DoSomething();
 	}
}

class A
{
 	public virtual void DoSomething()
 	{
 		Console.WriteLine("I did something in A's method!");
 	}
}

class B : A
{
 	public override void DoSomething()
 	{
 		Console.WriteLine("I did something in B's method!");
 	}
}
```

Output:

```
I did something in A's method!
I did something in B's method!
```

Both objects were passed as type `A`, yet had different implementations of the same method!

It is time to introduce the `sealed` keyword. If using `virtual` is like raising your hand, then using `sealed` is equivalent to keeping your hand down. And unlike that one teacher who tries to engage the whole class, the C# compiler will simply not call on that method/field to be overriden in a form of the class.

Yet another *high octane* example with us introducing class `C`:

```cs
class A
{
 	public virtual void DoSomething()
 	{
 		Console.WriteLine("I did something in A's method!");
 	}
}

class B : A
{
 	public sealed override void DoSomething()
 	{
 		Console.WriteLine("I did something in B's method!");
 	}
}

class C : B
{
 	public override void DoSomething()
 	{
 		Console.WriteLine("I did something in C's method!");
 	}
}
```

Output:

```
error CS0239: 'C.DoSomething()': cannot override inherited member 'B.DoSomething()'
```

So we can see that `sealed` cuts off the chain of overriding methods.

I know at this point you are in a code-induced coma from the amazing keywords you just learned how to use, but let me sneak one last keyword in the pile. Continuing with the classroom analogy, the `new` keyword is similar to that one overly enthusiastic student raising their hand and blocking another student behind them. This results in the teacher calling on the student in front, rather than the student behind. And before you freak out, I was also very surprised that the `new` keyword has another use than initializing objects.

***Note: When using a form of a class as that base class, any `new` methods/fields will not work in hiding the original ones.***

Example:

```cs
using System;

public class Program
{
	public static void Main(string[] args)
	{
 		DoStuff(new A());
 		DoStuff(new B());
 	}
 	static void DoStuff(A obj)
 	{
 		obj.DoSomething();
 	}
}

class A
{
 	public void DoSomething()
 	{
 		Console.WriteLine("I did something in A's method!");
 	}
}

class B : A
{
 	public new void DoSomething()
 	{
 		Console.WriteLine("I did something in B's method!");
 	}
}
```

Output:

```
I did something in A's method!
I did something in A's method!
```

The `new` keyword failed because of passing `B` as type `A`. (this is why `override` exists!) An example of `new` working:

```cs
using System;

public class Program
{
 	public static void Main(string[] args)
 	{
 		new A().DoSomething();
 		new B().DoSomething();
 	}
}

class A
{
 	public void DoSomething()
 	{
 		Console.WriteLine("I did something in A's method!");
 	}
}

class B : A
{
 	public new void DoSomething()
 	{
 		Console.WriteLine("I did something in B's method!");
 	}
}
```

Output:

```
I did something in A's method!
I did something in B's method!
```

Now, this hurts me as much as it hurts you, but I need to introduce one last keyword. And I know I said that `new` would be the last, but this is what happens when you trust a C# developer! Anyways, the last crucial keyword that you need to know is `base`. The `base` keyword allows you to access the base class methods and fields from a form of it, while not having to create a whole new object. It is just as convenient as it sounds.

Example:

```cs
using System;

public class Program
{
 	public static void Main(string[] args)
 	{
 		new B().DoSomething();
 	}
}

class A
{
 	public virtual void DoSomething()
 	{
 		Console.WriteLine("I did something in A's method!");
 	}
}

class B : A
{
 	public override void DoSomething()
 	{
 		Console.WriteLine("I did something in B's method!");
 		base.DoSomething();
 	}
}
```

Output:

```
I did something in B's method!
I did something in A's method!
```

If you want to learn about all of the possibilities of using polymorphism in C#, I would suggest further investigating [this Microsoft article](https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/object-oriented/polymorphism).

Thanks for reading!

([Cover image source](https://external-content.duckduckgo.com/iu/?u=http%3A%2F%2Ffullstackacademy.in%2Fwp-content%2Fuploads%2F2020%2F10%2FNew-Project.jpg&f=1&nofb=1))