25 Feb 2024
In C#, the two types of polymorphism are:
-
Compile-time (or static) polymorphism: This type of polymorphism is achieved using method overloading and operator overloading. Method overloading allows defining multiple methods with the same name but with different parameters in the same class. The compiler determines which method to call based on the number and type of arguments passed to it at compile time. Operator overloading allows defining operators such as +, -, *, /, etc., with custom implementations for user-defined types.
-
Run-time (or dynamic) polymorphism: This type of polymorphism is achieved using inheritance and method overriding. Method overriding allows a subclass to provide a specific implementation of a method that is already provided by its superclass. The method that is invoked is determined at runtime based on the actual type of the object rather than the reference type. Run-time polymorphism is often associated with the concept of virtual methods and the use of the override keyword in C#.
Compile-time Polymorphism Example (Method Overloading)
using System;
public class Calculator
{
// Method Overloading
public int Add(int a, int b)
{
return a + b;
}
public double Add(double a, double b)
{
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
Calculator calc = new Calculator();
int sumInt = calc.Add(5, 10); // Calls the first Add method
double sumDouble = calc.Add(4.5, 6.7); // Calls the second Add method
Console.WriteLine("Sum of integers: " + sumInt);
Console.WriteLine("Sum of doubles: " + sumDouble);
}
}
Explanation: In the above example, the Calculator class demonstrates compile-time polymorphism using method overloading. The Add method is overloaded with two different parameter types: int and double. Depending on the types of arguments passed during the method call, the compiler determines which version of the Add method to invoke.
Run-time Polymorphism Example (Method Overriding)
using System;
public class Shape
{
public virtual void Draw()
{
Console.WriteLine("Drawing a shape");
}
}
public class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a circle");
}
}
public class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("Drawing a rectangle");
}
}
class Program
{
static void Main(string[] args)
{
Shape shape1 = new Circle();
Shape shape2 = new Rectangle();
shape1.Draw(); // Calls the Draw method of Circle class
shape2.Draw(); // Calls the Draw method of Rectangle class
}
}
Explanation: In this example, we have a base class Shape with a virtual method Draw(). Two derived classes Circle and Rectangle override the Draw() method with their specific implementations. In the Main method, we create instances of Circle and Rectangle but assign them to variables of type Shape. When we call the Draw() method on these variables, the actual implementation of Draw() is determined at runtime based on the type of the object, showcasing run-time polymorphism in action.