Dynamic Polymorphism in .NET Core with Examples

Vineet Sharma
4 min readFeb 5, 2025

Introduction

Polymorphism is a key concept in Object-Oriented Programming (OOP) that enables objects to be treated as instances of their base type while still invoking the appropriate overridden method. In .NET Core, dynamic polymorphism is implemented using method overriding with inheritance and interfaces.

This blog explores dynamic polymorphism in .NET Core with practical examples and best practices.

What is Polymorphism?

Polymorphism allows objects to be used interchangeably while behaving differently based on their actual derived type.

There are two types of polymorphism:

  1. Static (Compile-time) Polymorphism: Achieved through method overloading and operator overloading.
  2. Dynamic (Runtime) Polymorphism: Achieved through method overriding using base and derived classes.

In this blog, we focus on dynamic polymorphism.

Implementing Dynamic Polymorphism in .NET Core

1. Using Method Overriding

Method overriding allows a derived class to provide a specific implementation of a method that is already defined in its base class.

Example 1: Method Overriding

using System;

class Animal
{
public virtual void Speak()
{
Console.WriteLine("Animal makes a sound");
}
}
class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("Dog barks");
}
}
class Cat : Animal
{
public override void Speak()
{
Console.WriteLine("Cat meows");
}
}
class Program
{
static void Main()
{
Animal myAnimal = new Dog();
myAnimal.Speak(); // Output: Dog barks
myAnimal = new Cat();
myAnimal.Speak(); // Output: Cat meows
}
}

Explanation

  • The Speak method in the base class Animal is declared as virtual, allowing derived classes to override it.
  • Dog and Cat classes override Speak and provide their own implementations.
  • The base class reference is used to invoke the overridden methods at runtime.

2. Using Interfaces for Dynamic Polymorphism

Interfaces allow multiple classes to implement the same method differently, achieving polymorphism.

Example 2: Interface Implementation

using System;

interface IShape
{
void Draw();
}
class Circle : IShape
{
public void Draw()
{
Console.WriteLine("Drawing a Circle");
}
}
class Square : IShape
{
public void Draw()
{
Console.WriteLine("Drawing a Square");
}
}
class Program
{
static void Main()
{
IShape shape = new Circle();
shape.Draw(); // Output: Drawing a Circle
shape = new Square();
shape.Draw(); // Output: Drawing a Square
}
}

Explanation

  • IShape interface defines a Draw method.
  • Circle and Square implement the Draw method differently.
  • The interface reference is used to invoke the appropriate method at runtime.

3. Abstract Classes vs. Interfaces in Dynamic Polymorphism

Feature Abstract Class Interface Methods Can have both abstract and concrete methods Only method declarations (default methods allowed in C# 8) Fields Can have fields Cannot have fields Multiple Inheritance Single inheritance only Can be implemented by multiple classes Constructors Can have constructors Cannot have constructors

When to use what?

  • Use abstract classes when sharing base functionality among derived classes.
  • Use interfaces when different classes must follow a common contract without shared base functionality.

4. Practical Use Cases of Dynamic Polymorphism

Case 1: Logging System

A logging system with multiple loggers implementing a common interface.

interface ILogger
{
void Log(string message);
}

class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine("Console Log: " + message);
}
}
class FileLogger : ILogger
{
public void Log(string message)
{
System.IO.File.WriteAllText("log.txt", message);
}
}
class LoggerClient
{
public static void LogMessage(ILogger logger, string message)
{
logger.Log(message);
}
}
class Program
{
static void Main()
{
ILogger logger = new ConsoleLogger();
LoggerClient.LogMessage(logger, "Application started");
}
}

Case 2: Payment Processing System

A system that processes payments using different payment methods.

interface IPaymentProcessor
{
void ProcessPayment(double amount);
}

class CreditCardPayment : IPaymentProcessor
{
public void ProcessPayment(double amount)
{
Console.WriteLine("Processing credit card payment of $" + amount);
}
}
class PayPalPayment : IPaymentProcessor
{
public void ProcessPayment(double amount)
{
Console.WriteLine("Processing PayPal payment of $" + amount);
}
}
class PaymentClient
{
public static void MakePayment(IPaymentProcessor processor, double amount)
{
processor.ProcessPayment(amount);
}
}
class Program
{
static void Main()
{
IPaymentProcessor payment = new CreditCardPayment();
PaymentClient.MakePayment(payment, 100.50);
}
}

Best Practices for Dynamic Polymorphism

  1. Use base class references to achieve runtime polymorphism.
  2. Declare base class methods as virtual and override them in derived classes.
  3. Use interfaces to define common behaviors across different classes.
  4. Follow SOLID principles to ensure maintainability and scalability.
  5. Use dependency injection to manage dependencies efficiently in .NET Core applications.

Conclusion

Dynamic polymorphism is a powerful OOP feature that enhances flexibility and reusability in .NET Core applications. By using method overriding, abstract classes, and interfaces, developers can design scalable and maintainable applications.

Would you like to explore advanced topics such as dependency injection with polymorphism in .NET Core? Let me know in the comments!

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response