Polymorphism in C#

Last Updated : 22 Oct, 2026

Polymorphism is one of the fundamental concepts of Object-Oriented Programming (OOP) that allows a common interface or method name to represent different behaviors. It enables methods to behave differently based on the arguments supplied or the actual object type, improving code flexibility and reusability.

  • Polymorphism means "many forms" and allows related operations to have different implementations.
  • Supports compile-time polymorphism through method overloading and runtime polymorphism through method overriding.
  • It helps developers write extensible, reusable, and maintainable applications.

Example: Consider a person who can have different roles, such as a father, husband, or employee. Each role can have its own behavior. This concept can be represented using inheritance and method overriding.

C#
using System;

// Base class
class Person{
    public virtual void Role(){
        Console.WriteLine("I am a person.");
    }
}

// Derived class
class Father : Person{
    
    public override void Role(){
        
        Console.WriteLine("I am a father.");
    }
}

class Geeks{
    static void Main(){
        
        // Base class reference with derived class object
        Person p = new Father();

        // Calls the overridden method
        p.Role();
    }
}

Output
I am a father.

Explanation: The Person class defines a virtual method Role(), while the Father class overrides it to provide a specific implementation. When Role() is called using a Person reference pointing to a Father object, the overridden method executes at runtime. This demonstrates runtime polymorphism.

Types of Polymorphism

There are two types of polymorphism

types_of_polymorphism
types of Polymorpshism

1. Compile Time Polymorphism

Compile-time polymorphism, also known as static polymorphism, occurs when the compiler determines which method implementation to call based on the method name and arguments. It is commonly achieved through method overloading.

  • Method selection occurs at compile time.
  • It allows multiple methods to share the same name while accepting different parameters.

Method Overloading

Method overloading allows a class to define multiple methods with the same name but different parameter lists. The compiler selects the appropriate overload based on the arguments provided.

The parameter lists can differ in:

  • Number of parameters
  • Types of parameters
  • Order of parameter types

Syntax:

class Demo{
public void Show(int a){
}
public void Show(int a, int b) {
}
}

Example: Method overloading using different parameter types.

C#
using System;

class Helper{
    
    // Method with two integer parameters
    public static int Multiply(int a, int b){
        return a * b;
    }

    // Method with two double parameters
    public static double Multiply(double a, double b){
        return a * b;
    }
}

class Geeks{
    static void Main(){
        
        Console.WriteLine(Helper.Multiply(2, 4));
        Console.WriteLine(Helper.Multiply(5.5, 6.3));
    }
}

Output
8
34.65

Explanation: The Multiply() method is overloaded with two parameter types: int and double. When integer arguments are passed, the compiler selects the integer overload. When double arguments are passed, it selects the double overload.

2. Runtime Polymorphism

Runtime polymorphism, also known as dynamic polymorphism, occurs when the implementation of an overridden method is selected during program execution. It is commonly achieved through method overriding.

  • Method implementation is selected at runtime.
  • It depends on the actual object type rather than the reference type.

Method Overriding

Method overriding occurs when a derived class provides its own implementation of a virtual or abstract method declared in its base class. The base-class method must be marked as virtual, abstract, or already be an override, while the derived class uses the override keyword.

Syntax:

class Parent{
public virtual void Print(){
}
}

class Child : Parent{
public override void Print(){
}
}

Example: Program to demonstrates method overriding, where two derived classes provide their own implementations of the Print() method.

C#
using System;

// Base class
class Parent{
    public virtual void Print(){
        Console.WriteLine("parent class");
    }
}

// Derived class 1
class Subclass1 : Parent{
    public override void Print(){
        Console.WriteLine("subclass1");
    }
}

// Derived class 2
class Subclass2 : Parent{
    public override void Print(){
        Console.WriteLine("subclass2");
    }
}

class Geeks{
    static void Main(){
        Parent a;

        a = new Subclass1();
        a.Print();

        a = new Subclass2();
        a.Print();
    }
}

Output
subclass1
subclass2

Explanation: Subclass1 and Subclass2 override the Print() method inherited from Parent. Although a is a reference of type Parent, C# invokes the appropriate overridden method based on the actual object assigned to it. This demonstrates runtime polymorphism.

Compile-Time Vs Runtime Polymorphism

The following table highlights the main differences between compile-time and runtime polymorphism.

Feature

Compile-Time Polymorphism

Runtime Polymorphism

Also called

Static polymorphism

Dynamic polymorphism

Mainly achieved using

Method overloading

Method overriding

Method selection

At compile time

At runtime

Inheritance required

No, Not required

Yes, for class method overriding

Keywords

No special keyword is required for basic overloading

virtual, override, abstract

Example

Multiply(int, int) and Multiply(double, double)

Dog.Sound() overriding Animal.Sound()

Advantages of Polymorphism

  • Code Reusability: Allows common code to work with objects of different related types.
  • Flexibility: Supports multiple implementations through a common base class or interface.
  • Maintainability: Helps organize related behavior and reduce repetitive conditional logic.
  • Extensibility: New derived classes can provide their own implementations without changing existing code that works through the base abstraction.
  • Loose Coupling: Allows code to depend on abstractions rather than specific implementations.

Disadvantages of Polymorphism

  • Increased Complexity: Method overriding and inheritance hierarchies may make code harder to understand.
  • Debugging Difficulty: Runtime method dispatch can make it less obvious which implementation executes.
  • Performance Overhead: Virtual method calls may involve a small runtime dispatch cost, although the .NET runtime can optimize many such calls.
  • Maintenance Challenges: Poorly designed inheritance relationships and excessive overloading can make code difficult to maintain.
  • Ambiguous Overloads: Certain combinations of overloaded methods and arguments can result in compile-time ambiguity.
Comment

Explore