Joydip Kanjilal
Contributor

How to implement polymorphism in C#

opinion
Jan 20, 20164 mins
Software Development

Take advantage of polymorphism to isolate interface from implementation and promote flexibility in your designs

Polymorphism refers to the ability to present the same interface for different forms. Although the concept of polymorphism is the same in all programming languages that support it, its implementation differs from one language to another.

The three types of polymorphism are overloading, parametric, and inclusion. Polymorphism helps to promote flexibility in designs by allowing the same method to have different implementations. In essence, you can leverage polymorphism to separate interface from implementation. It promotes code reuse and separation of concerns in your application.

Overloading polymorphism is a type that exists in classes that are independent of each other — they are not related (inheritance, dependency, etc.) to each other in any way. As an example, you can have two distinct classes not related in any way with each other and having a method with the same name. Operator overloading is an example of this type of polymorphism.

Parametric polymorphism, or template polymorphism, is a type where you have more than one method in your class with identical names but varying parameters, i.e., they all have the same method names, but they differ in the parameters.

Inclusion polymorphism is also known as redefinition or method overriding. In this type of polymorphism, a sub class can redefine a method of the base class. This ability is also known as specialization.

Parametric polymorphism

This refers to the form of polymorphism where you have more than one method in your class that has the same name but they differ in their method signatures. A method signature comprises of the return type of the method, the type of the parameters to the method and the sequence of these parameters. Hence, a method that accepts an integer and a character as an argument differs in the signature from another method that accepts a character and an integer as arguments even though the return types of both these methods (having identical method names) are the same. The compiler determines the exact method to be called by comparing the method signatures of the overloaded methods.

The following code listing illustrates how method overloading can be implemented.

public enum Severity

    {

        Informational, Warning, Critical

    }

    public class Logger

    {

        public void Log(string message)

        {

            //Some code

        }

        public void Log(string message, Severity severity)

        {

            //Some code

        }

    }

Refer to the code listing above. Note how the Log() method has been overloaded.  This is an example of compile time polymorphism.

Inclusion polymorphism

Inclusion polymorphism, or method overriding, can be achieved in C# using virtual methods. In method overriding, you have methods having identical signatures present in both the base and the derived classes. You would typically want to use virtual methods to implement run-time polymorphism or late binding. Note that a virtual method is one that is declared as virtual in the base class and you can allow the subclasses of the type to override the virtual method(s).

The following code snippet shows two classes — the base class named Logger that contains a virtual method called Log and a derived class named FileLogger that extends the Logger class and overrides the Log method of the base class.

public class Logger

    {

        public virtual void Log(string message)

        {

            Console.WriteLine("Inside the Log method of the base class Logger");

        }

    }

    public class FileLogger : Logger

    {

        public override void Log(string message)

        {

            Console.WriteLine("Inside the Log method of the FileLogger class");

        }

    }

This is an example of method overriding. Both the base and the derived classes have the same method with identical signatures. We use method overriding to implement run time polymorphism or late binding. The following code snippet shows how the Log method can be called using a reference of the base class.

static void Main(string[] args)

        {

            Logger logger = new FileLogger();

            logger.Log("Hello World!");

            Console.ReadKey();

        }

When you execute the above code snippet, the Log method of the derived class, i.e., the Filelogger class would be invoked. If the Log method wasn’t declared as virtual in the base class, the base version of the Log method would have been called instead. Since this binding occurs late at run-time, this type of polymorphism is known as run-time polymorphism or late binding.

Joydip Kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author