C# Polymorphism

Polymorphism is a concept in object-oriented programming (OOP), it refers to the ability of an object to take on many forms.. It enables a single method, function, or operator to work in different ways depending on the type of object it is acting upon.

In simple terms, polymorphism means "many forms", where one interface or method can have multiple behaviors based on the object that invokes it.

There are two types of polymorphism in C#:

  • Compile-time polymorphism (Static polymorphism): Achieved using method overloading and operator overloading.

  • Run-time polymorphism (Dynamic polymorphism): Achieved using method overriding with inheritance and interfaces.

Example 1: Compile-Time Polymorphism (Method Overloading)

By using method overloading we can have multiple methods with the same name but different parameters to exist in the same class.


using System;

public class Printer
{
    // Method 1: Print an integer
    public void Print(int number)
    {
        Console.WriteLine("Printing integer: " + number);
    }

    //  Method 2: Print a string
    public void Print(string text)
    {
        Console.WriteLine("Printing string: " + text);
    }
}

class Program
{
    static void Main()
    {
        Printer printer = new Printer();
        printer.Print(5);        // Calls Print(int number) method
        printer.Print("Hello");  // Calls Print(string text) method
    }
}

Output:


Printing integer: 5
Printing string: Hello

In this case, the Print method is overloaded to handle both the integer and string values which demonstrates compile-time polymorphism.


Example 2: Run-Time Polymorphism (Method Overriding)

Run-time polymorphism occurs when a method in a base class is overridden by the method in the derived(child) class.


using System;

public class Animal
{
    // Base class method
    public virtual void Speak()
    {
        Console.WriteLine("Animal makes a sound.");
    }
}

public class Dog : Animal
{
    // Here Overriding the Speak method in the derived class using override keyword.
    public override void Speak()
    {
        Console.WriteLine("Dog barks.");
    }
}

public class Cat : Animal
{
    // Overriding the Speak method in the derived class
    public override void Speak()
    {
        Console.WriteLine("Cat meows.");
    }
}

class Program
{
    static void Main()
    {
        Animal myAnimal = new Animal();
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myAnimal.Speak();
        myDog.Speak();
        myCat.Speak();
    }
}

Output:


Animal makes a sound. 
Dog barks 
Cat meows.

Here, the Speak() method is defined in the base class Animal, and it is overridden in the derived classes Dog and Cat. When calling Speak() on an Animal reference that points to a Dog or Cat, the appropriate overridden method is invoked. This is an example of run-time polymorphism.

Key Points to Remember:

  • Compile-time polymorphism is resolved at the compile time, and it can be achieved through method overloading.

  • Run-time polymorphism is resolved at the run time, and it requires inheritance and method overriding (using the virtual keyword in the base class and the override keyword in the derived class).
Conclusion

Polymorphism allows developers to write more generic and extensible code, which makes it easier to maintain and scale applications. It also helps to improve code organization and supports principles like inheritance and abstraction, which are key to object-oriented design.