Polymorphism in C#

Last Updated : 9 Apr, 2026

Polymorphism is one of the four pillars of object-oriented programming. It allows a single interface to represent different implementations. The word polymorphism means "many forms". Example:

C#
using System;
class Geeks
{
    // method without any parameter 
    public void greet()
    {
        Console.WriteLine("Hello");
    }

    // method takes a single string parameter
    public void greet(string name)
    {
        Console.WriteLine("Hello " + name);
    }

    static void Main(string[] args)
    {
        Geeks p1 = new Geeks();

        // calls method without any argument
        p1.greet();

        // calls method with an argument
        p1.greet("Geeks");

    }
}

Output
Hello
Hello Geeks
  • The class Geeks defines two methods with the same name greet but different parameter lists.
  • This is an example of method overloading, which is a form of compile-time polymorphism.
  • The method to be executed is determined by the number and type of arguments passed at compile time.
  • When p1.greet() is called, it executes the version without parameters.
  • When p1.greet("Geeks") is called, it executes the version with a string parameter.
  • The same method name (greet) exhibits multiple forms of behavior, which is the essence of polymorphism.

Types of Polymorphism

There are two types of polymorphism

  • Compile-time Polymorphism
  • Runtime Polymorphism
c_polymorphism
Polymorphism in C#

Compile Time Polymorphism

It is achieved by method overloading or operator overloading. The method to be executed is determined at compile time.

1. Method Overloading: Multiple methods in the same class share the same name but differ in the number or type of parameters. The correct method is selected by the compiler based on the arguments provided.

C#
using System;

class Calculator {
    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() {
        Calculator calc = new Calculator();
        Console.WriteLine(calc.Add(5, 10));     // Calls int version
        Console.WriteLine(calc.Add(2.5, 3.5));  // Calls double version
    }
}

Output
15
6

Explanation:

  • The class Calculator defines two methods with the same name Add but different parameter lists (one takes int, the other takes double).
  • This is an example of method overloading, where multiple methods share the same name but differ by parameter type or number.
  • The decision about which method to call (Add(int, int) or Add(double, double)) is made by the compiler at compile time based on the arguments passed.

2. Operator Overloading: Operator overloading in C# allows redefining the behavior of operators for user-defined types. It enables operators to perform custom operations when applied to objects of a class or struct.

C#
using System;
namespace Calculator
{
	
class Calculator{
	
	public int number1 , number2;
	public Calculator(int num1 , int num2){
		number1 = num1;
		number2 = num2;
	}
	
// Function to perform operation by changing sign of integers
public static Calculator operator -(Calculator c1){
	c1.number1 = -c1.number1;
	c1.number2 = -c1.number2;
	return c1;
}

// Function to print the numbers
public void Print(){
	Console.WriteLine ("Number1 = " + number1);
	Console.WriteLine ("Number2 = " + number2);
}
}

class EntryPoint{	
	static void Main(String []args){ 
		
		// using overloaded - operator with the class object
		Calculator calc = new Calculator(15, -25);
		
		calc = -calc;
		
		calc.Print();
	}
}
}

Output
Number1 = -15
Number2 = 25

Explanation:

  • The Calculator has a constructor to initialize two integers, number1 and number2.
  • The unary operator is overloaded to change the sign of both numbers in the Calculator object.
  • In the Main method, the overloaded operator is used to negate the values of the Calculator object, and the result is printed.

Note: Operator overloading is a form of compile-time polymorphism because the compiler decides which operator version to call based on the operand types at compile time.

Runtime Polymorphism (Method Overriding)

Runtime polymorphism (dynamic polymorphism) in C# is achieved through method overriding. It occurs when a derived class provides a specific implementation of a method already defined in the base class, using the same method name, parameters, and return type. This allows the derived class to modify or extend the behavior of the inherited method.

Key Points:

  • Virtual Method: The base class method must be declared as virtual to allow overriding.
  • Override Keyword: The derived class method must use the override keyword to provide a new implementation.

Example:

C#
using System;

namespace Geeks
{
    // Base class
    class Animal{
        // Virtual method to allow overriding
        public virtual void MakeSound(){
            Console.WriteLine("Animal makes a sound");
        }
    }

    // Derived class
    class Dog : Animal
    {
        // Overriding the base class method
        public override void MakeSound()
        {
            Console.WriteLine("Dog barks");
        }
    }

    // Derived class
    class Cat : Animal
    {
        // Overriding the base class method
        public override void MakeSound()
        {
            Console.WriteLine("Cat meows");
        }
    }

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

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

Output
Animal makes a sound
Dog barks
Cat meows

Explanation:

  • In this example, the Animal class defines a virtual method MakeSound. The Dog and Cat classes override this method using the override keyword to provide their own implementations.
  • At runtime, when a base class reference (Animal) points to a derived object (Dog or Cat), the overridden method of the actual object is called. This behavior is known as runtime polymorphism.

Use Case and Behavior of Polymorphism

  • Allows methods to be written in a more general form, making code easier to extend and maintain.
  • Enhances the flexibility of the code and makes it easier to maintain.
  • Enables the use of a uniform interface, which simplifies the design of systems that can handle different data types and objects consistently.
Comment

Explore