Diving in OOP (Day 3): Polymorphism and Inheritance (Dynamic Binding/Run Time Polymorphism)


1. Introduction

This part of the article series will focus more on run time polymorphism also called late binding. We’ll use the same technique of learning, less theory and more hands-on. We’ll take small code snippets to learn the concept more deeply. To master this concept is like learning more than 50% of OOP.

2. Pre-requisites

Since this is the third part of the series, I expect my readers to be experts in compile time polymorphism and inheritance. Although it doesn’t matter if you are directly starting to learn from this article, you can take the other articles later.

3. Roadmap

Our roadmap for learning OOP is clear, but let’s just revise it:

4. Runtime Polymorphism or Late Binding or Dynamic Binding

In simple C# language, in run time polymorphism or method overriding, we can override a method in base class by creating similar method in derived class this can be achieved by using inheritance principle and using “virtual & override” keywords.

5. What are New and Override Keywords in C#?

Create a console application named InheritanceAndPolymorphism in your Visual Studio.
Just add two classes and keep the Program.cs as it is.The two classes will be named ClassA.cs and ClassB.cs and add one method in each class as follows:

ClassA

public class ClassA
    {
        public void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }

public void BBB()
{
Console.WriteLine(ClassA BBB”);
}

public void CCC()
{
Console.WriteLine(ClassA CCC”);
}
}

ClassB

    public class ClassB
    {
        public void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }

public void BBB()
{
Console.WriteLine(ClassB BBB”);
}

public void CCC()
{
Console.WriteLine(ClassB CCC”);
}
}

Program.cs

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {

}
}

We see both classes ClassA and ClassB have the same number of methods with similar names in both the classes. Now let’s inherit ClassA from ClassB, and create instances of the classes and call their methods in program.cs.
So our code for the two classes becomes:
/// <summary>
    /// ClassB, acting as a base class
    /// </summary>
    public class ClassB
    {
        public void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }

public void BBB()
{
Console.WriteLine(ClassB BBB”);
}

public void CCC()
{
Console.WriteLine(ClassB CCC”);
}
}

/// <summary>
/// Class A, acting as a derived class
/// </summary>
public class ClassA : ClassB
{
public void AAA()
{
Console.WriteLine(ClassA AAA”);
}

public void BBB()
{
Console.WriteLine(ClassA BBB”);
}

public void CCC()
{
Console.WriteLine(ClassA CCC”);
}
}

Program.cs

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassA x = new ClassA();
            ClassB y=new ClassB();
            ClassB z=new ClassA();

x.AAA(); x.BBB(); x.CCC();
y.AAA(); y.BBB();y.CCC();
z.AAA(); z.BBB(); z.CCC();
}
}

Now press F5, i.e., run the code, what do we get?

Output

ClassB AAA
ClassB BBB
ClassB CCC
ClassA AAA
ClassA BBB
ClassA CCC
ClassB AAA
ClassB BBB
ClassB CCC
But with the output, we also got three warnings.

Warnings

'InheritanceAndPolymorphism.ClassA.AAA()' hides inherited member 
'InheritanceAndPolymorphism.ClassB.AAA()'. Use the new keyword if hiding was intended.

‘InheritanceAndPolymorphism.ClassA.BBB()’ hides inherited member
‘InheritanceAndPolymorphism.ClassB.BBB()’. Use the new keyword if hiding was intended.

‘InheritanceAndPolymorphism.ClassA.CCC()’ hides inherited member
‘InheritanceAndPolymorphism.ClassB.CCC()’. Use the new keyword if hiding was intended.

 
Point to remember: In C#, a smaller object could be equated to a bigger object.
Class ClassB is the super class of class ClassA. That means ClassA is the derived class and ClassB is the base class. The class ClassA comprises ClassB and something more. So we can conclude that object of ClassA is bigger than object of ClassB. Since ClassA is inherited from ClassB, it contains its own methods and properties. Moreover, it will also contain methods/properties that are inherited from ClassB too.
Let’s take the case of object y. It looks like ClassB and initialized by creating an object that also looks like ClassB, well and good. Now, when we call the methods AAA and BBB and CCC through the object y, we know that it will call them from ClassB.
Object x looks like that of ClassA, i.e., the derived class. It is initialized to an object that looks like ClassA. When we call AAABBB and CCC method through x, it calls AAABBB and CCC from ClassA.
Now there is a somewhat tricky situation we are dealing with:
Object z again looks like ClassB, but it is now initialized to an object that looks like ClassA which does not give an error as explained earlier. But there is no change at all in the output we get and the behavior is identical to that of object y.Therefore initializing it to an object that looks like ClassB or ClassA does not seem to matter.

6. Experiment

Let’s experiment with the code, and put override behind AAA and new behind BBB methods of ClassA, i.e., the derived class.
Our code is as follows:

ClassB

    /// <summary>
    /// ClassB, acting as a base class
    /// </summary>
    public class ClassB
    {
        public void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }

public void BBB()
{
Console.WriteLine(ClassB BBB”);
}

public void CCC()
{
Console.WriteLine(ClassB CCC”);
}
}

ClassA

    /// <summary>
    /// Class A, acting as a derived class
    /// </summary>
    public class ClassA : ClassB
    {
        public override void AAA()
        {
            Console.WriteLine("ClassA AAA");
        }

public new void BBB()
{
Console.WriteLine(ClassA BBB”);
}

public void CCC()
{
Console.WriteLine(ClassA CCC”);
}
}

Program.cs

    /// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassB y = new ClassB();
            ClassA x = new ClassA();
            ClassB z = new ClassA();

y.AAA(); y.BBB(); y.CCC();
x.AAA(); x.BBB(); x.CCC();
z.AAA(); z.BBB(); z.CCC();

Console.ReadKey();
}
}

We get output:
Error:  'InheritanceAndPolymorphism.ClassA.AAA()': cannot override inherited member 
'InheritanceAndPolymorphism.ClassB.AAA()' because it is not marked virtual, abstract, or override
InheritanceAndPolymorphism: It’s the namespace I used for my console application, so you can ignore that.
We got an error after we added these two modifiers in the derived class methods, the error tells us to mark the methods virtualabstract or override in the base class.
OK, how does it matter to me?
I marked all the methods of base class as virtual.
Now our code and output looks like:
/// <summary>
    /// ClassB, acting as a base class
    /// </summary>
    public class ClassB
    {
        public virtual void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }

public virtual void BBB()
{
Console.WriteLine(ClassB BBB”);
}

public virtual void CCC()
{
Console.WriteLine(ClassB CCC”);
}
}

/// <summary>
/// Class A, acting as a derived class
/// </summary>
public class ClassA : ClassB
{
public override void AAA()
{
Console.WriteLine(ClassA AAA”);
}

public new void BBB()
{
Console.WriteLine(ClassA BBB”);
}

public void CCC()
{
Console.WriteLine(ClassA CCC”);
}
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
public class Program
{
private static void Main(string[] args)
{
ClassB y = new ClassB();
ClassA x = new ClassA();
ClassB z = new ClassA();

y.AAA(); y.BBB(); y.CCC();
x.AAA(); x.BBB(); x.CCC();
z.AAA(); z.BBB(); z.CCC();

Console.ReadKey();
}
}

Output

ClassB AAA
ClassB BBB
ClassB CCC
ClassA AAA
ClassA BBB
ClassA CCC
ClassA AAA
ClassB BBB
ClassB CCC
 
Point to remember: The override modifier is needed as the derived class methods will get first priority and be called upon.
We see here that there is only a single small change in the workings of the object z only and not in x and y. This strange output occurred only after we added virtual modifier in the base class methods. The difference is in the objectzz looks like the base class ClassB but is initialized to an instance that looks like that of derived class ClassA. C# knows this fact. When we run z.AAA(), C# remembers that instance z was initialized by a ClassA object and hence it first goes to class ClassA, too obvious. Here the method has a modifier override which literally means, forget about the data type of which is ClassB, call AAA from ClassA as it overrides the AAA of the base class. The override modifier is needed as the derived class methods will get first priority and be called upon.
We wanted to override the AAA of the base class ClassB. We are infact telling C# that this AAA is similar to the AAAof the one in base class.
New keyword acts in the exact opposite to override keyword. The method BBB as we see has the new modifier.z.BBB() calls BBB from ClassB and not ClassA. New means that the method BBB is a new method and it has absolutely nothing to do with the BBB in the base class. It may have the same name i.e. BBB as in the base class, but that is only a coincidence. As z looks like ClassB, the BBB of ClassB gets called even though there is a BBB inClassA. When we do not write any modifier, then it is assumed that we wrote new. So every time we write a method, C# assumes it has nothing to do with the base class.
 
Point to remember: These modifiers like new and override can only be used if the method in the base class is avirtual method. Virtual means that the base class is granting us permission to invoke the method from the derived class and not the base class. But, we have to add the modifier override if our derived class method has to be called.

7. Run Time Polymorphism with Three Classes

Let’s get into some more action. Let’s involve one more class in the play. Let’s add a class named ClassC, and design our three classes and program.cs as follows:
    /// <summary>
    /// ClassB, acting as a base class
    /// </summary>
    public class ClassB
    {
        public  void AAA()
        {
            Console.WriteLine("ClassB AAA");
        }

public virtual void BBB()
{
Console.WriteLine(ClassB BBB”);
}

public virtual void CCC()
{
Console.WriteLine(ClassB CCC”);
}
}

/// <summary>
/// Class A, acting as a derived class
/// </summary>
public class ClassA : ClassB
{
public virtual void AAA()
{
Console.WriteLine(ClassA AAA”);
}

public new void BBB()
{
Console.WriteLine(ClassA BBB”);
}

public override void CCC()
{
Console.WriteLine(ClassA CCC”);
}
}

/// <summary>
/// Class C, acting as a derived class
/// </summary>
public class ClassC : ClassA
{
public override void AAA()
{
Console.WriteLine(ClassC AAA”);
}

public void CCC()
{
Console.WriteLine(ClassC CCC”);
}
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
public class Program
{
private static void Main(string[] args)
{
ClassB y = new ClassA();
ClassB x = new ClassC();
ClassA z = new ClassC();

y.AAA(); y.BBB(); y.CCC();
x.AAA(); x.BBB(); x.CCC();
z.AAA(); z.BBB(); z.CCC();

Console.ReadKey();
}
}

Output

ClassB AAA
ClassB BBB
ClassA CCC
ClassB AAA
ClassB BBB
ClassA CCC
ClassC AAA
ClassA BBB
ClassA CCC
Don’t be scared of the long example that we have taken. This will help you to learn the concept in detail. We have already learned that we can initialize a base object to a derived object. But vice versa will result into error. This leads to an instance of a base class being initialized to an instance of the derived class. So the question is now that which method will be called when. The method from the base class or from the derived class.
 
Point to remember: If the base class object declared the method virtual and the derived class used the modifieroverride, the derived class method will get called. Otherwise the base class method will get executed. Therefore forvirtual methods, the data type created is decided at run time only.
 
Point to remember: All the methods not marked with virtual are non virtual, and the method to be called is decided at compile time, depending upon the static data type of the object.
If the object of a class is initialized to the same data type, none of the above rule would apply. Whenever we have a mismatch, we always need rules to resolve the mismatch. So we can land up with a scenario where an object to a base class can call a method in the derived class.
The object y that looks like of ClassB but is initialized here to the derived class, i.e., ClassA.
y.AAA() first looks into the class ClassB. Here, it verifies whether the method AAA is marked virtual. The answer is an emphatic no and hence everything comes to halt and the method AAA gets called from class ClassB.
y.BBB also does the same thing, but the method now is defined virtual in class ClassB. Thus C# looks at the classClassB, the one it was initialized to. Here BBB is marked with the modifier “new”. That means BBB is a new method which has nothing to do with the one in the base class. They only accidentally share the same name. So as there is no method called BBB (as it is a new BBB) in the derived class, the one from base class gets called. In the scene ofy.CCC(), the same above steps are followed again, but in the class ClassB, we see the modifier override, that by behaviour overrides the method in the base class. We are actually telling C# to call this method in class ClassA and not the one in the base class, i.e., ClassB.
I just got this picture from the internet that depicts our current situation of classes. We are learning the concept like charm now. OOP is becoming easy now.
The object x which also looks like that of class ClassB is now initialized with an object that looks like our newly introduced class ClassC and not ClassA like before. Since AAA is a non virtual method, it gets called from ClassB. In the case of method BBB, C# now looks into class ClassC. Here, it does not find a method named BBB and so ultimately propagates and now looks into class ClassA. Therefore the above rules repeat on and on and it gets called from class ClassB. In the case of x.CCC, in class ClassC, it is already marked new by default and therefore this method has nothing to do with the one declared in class ClassB. So the one from ClassC does not get called but the one from class ClassB where it is marked as override.
Now if we modify a bit our CCC method in ClassC and change it to the code as shown below:
        public override void CCC()
        {
            Console.WriteLine("ClassC CCC");
        }
We changed default new to override, the CCC of ClassC will now be called.
The last object z looks like that of ClassA but is now initialized to an object that looks like the derived class ClassC, we know we can do this. So z.AAA() when called, looks first into class ClassA where it is flagged as virtual. Do you recall that AAA is non virtual in class ClassB but marked as a virtual in ClassA. From now on, the method AAA is virtual in ClassC also but not in class ClassBVirtual always flows from upwards to downwards like a waterfall. Since AAA() is marked virtual, we now look into class ClassC. Here it is marked override and thereforeAAA() gets called from class ClassC. In the case of BBB()BBB() is marked virtual in class ClassB and new inClassA, but as there is no method BBB in ClassC, none of the modifier matters at all in this case. Finally it gets invoked from class ClassA. At last for method CCC, in class ClassC it is marked as new. Hence, it has no relation with the CCC in class ClassA which results in method CCC gets invoked from ClassA but not ClassB.
One more example:
    internal class A
    {
        public virtual void X()
        {
        }
    }

internal class B : A
{
public new void X()
{
}
}

internal class C : B
{
public override void X()
{
}
}

In the above example, the code is very much self explanatory, the output which we’ll get is:
Error: 'InheritanceAndPolymorphism.C.X()': cannot override inherited member 
'InheritanceAndPolymorphism.B.X()' because it is not marked virtual, abstract, or override
Strange! We got an error as the method X() in class is marked new. That means it hides the X() of class A. If we talk about class Cdoes not supply a method named X. The method X defined in class B has nothing to do with the method defined in class A. This means that the method of class does not inherit the virtual modifier from the method X() of class A. This is what the compiler complained about. As the method X in B has no virtualmodifier, in C we cannot use the modifier override. We can, however, use the modifier new and remove the warning?

8. Cut Off Relations

    internal class A
    {
        public virtual void X()
        {
            Console.WriteLine("Class: A ; Method X");
        }
    }

internal class B : A
{
public new virtual void X()
{
Console.WriteLine(Class: B ; Method X”);
}
}

internal class C : B
{
public override void X()
{
Console.WriteLine(Class: C ; Method X”);
}
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
public class Program
{
private static void Main(string[] args)
{
A a = new C();
a.X();
B b = new C();
b.X();

Console.ReadKey();
}
}

Output

Class: A ; Method X
Class: C ; Method X
If in the above code, we remove the modifier override from X() in class C, we get:

Output

Class: A ; Method X
Class: B ; Method X
Yes, that’s the problem with virtual methods. Sometimes, they are too confusing, the result is entirely different with what we expect. Object looks like an but is initialized to the derived class C. Since is virtual, C# now goes and looks into class C. But before looking into the class C, it realizes that in class BX is new. That’s it, this thing cuts of all connection with the in A. Thus the keyword new is preceded with virtual, otherwise the override modifier would give us an error in class C. As in class is marked as new method, having nothing to do with the class A, class Cinherits a new which also has nothing to do with the class A. The in class is related to the of class and not of class A. Thus the of class gets invoked.
In the second case, object b looks like class now but in turn is initialized to an object of class C. C# first looks at classB. Here is new and virtual both, which makes it a unique method X. Sadly, the in has the override modifier which sees to it that the X of C hides the X of B. This calls the of instead. If we remove the override modifier from in class C, the default will be new, that cuts off the relation from the X of B. Thus, as it is, a new method, the Xof gets invoked.
virtual method cannot be marked by the modifiers staticabstract or override. A non virtual method is said to be invariant. This means that the same method gets called always, irrespective of whether one exists in the base class or derived class. In a virtual method, the run-time type of the object decides on which method to be called and not the compile-time type as is in the case of non virtual methods. For a virtual method, there exists a most derived implementation which always gets called.

9. Runtime Polymorphism with Four Classes

OK! We did a lot of coding. How about if I tell you that we are going to add one more class to our code, yes that is class ClassD. So we go more deep into the concept of Polymorphism and Inheritance.
We add one more class to the three classes solution on which we were working on (remember?). So our new class is named ClassD.
Let’s take our new class into action:
/// <summary>
    /// Class A
    /// </summary>
    public class ClassA
    {
        public virtual void XXX()
        {
            Console.WriteLine("ClassA XXX");
        }
    }

/// <summary>
/// ClassB
/// </summary>
public class ClassB:ClassA
{
public override void XXX()
{
Console.WriteLine(ClassB XXX”);
}
}

/// <summary>
/// Class C
/// </summary>
public class ClassC : ClassB
{
public virtual new void XXX()
{
Console.WriteLine(ClassC XXX”);
}
}

/// <summary>
/// Class D
/// </summary>
public class ClassD : ClassC
{
public override void XXX()
{
Console.WriteLine(ClassD XXX”);
}
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
public class Program
{
private static void Main(string[] args)
{
ClassA a = new ClassD();
ClassB b = new ClassD();
ClassC c=new ClassD();
ClassD d=new ClassD();

a.XXX();
b.XXX();
c.XXX();
d.XXX();

Console.ReadKey();
}
}

Output

ClassB XXX
ClassB XXX
ClassD XXX
ClassD XXX

Explanation

One last explanation of virtual and override will be a bit complex.
The first output, ClassB XXX, is the outcome of the statement a.XXX();. We have the method XXX marked virtual in class ClassA. Therefore, when using new keyword, we now proceed to class ClassB and not ClassD as explained earlier. Here, XXX has an override and since C# knows that class ClassC inherits this function XXX. In the classClassC, since it is marked as new, C# will now go back and not proceed further to class ClassD. Finally the methodXXX gets called from class ClassB as shown in the output above.
If we change the method XXX in class ClassC to override, then C# will proceed to class ClassD and call the XXX of class ClassD as it overrides the XXX of ClassC.
    /// <summary>
    /// Class C
    /// </summary>
    public class ClassC : ClassB
    {
        public override void XXX()
        {
            Console.WriteLine("ClassC XXX");
        }
    }
Remove the override from XXX in class ClassD and the method will get invoked from class ClassC as the default isnew.
When we talk about object b, everything seems similar to object a, as it overrides the XXX of class ClassA.
When we restore back the defaults, let’s have a look at the third line. Object here looks like ClassC. In class ClassC,XXX() is new and therefore it has no connection with the earlier XXX methods. In class ClassD, we actually override the XXX of class ClassC and so the XXX of ClassD gets invoked. Just remove the override and then it will get invoked from class ClassC. The object does not follow any of the above protocols as both the sides of the equal sign are of same data types.
 
Point to remember: An override method is a method that has the override modifier included on it. This introduces a new implementation of a method. We can’t use the modifiers such as newstatic or virtual along withoverride. But abstract is permitted.
Another example:
/// <summary>
    /// Class A
    /// </summary>
    public class ClassA
    {
        public virtual void XXX()
        {
            Console.WriteLine("ClassA XXX");
        }
    }

/// <summary>
/// ClassB
/// </summary>
public class ClassB:ClassA
{
public override void XXX()
{
base.XXX();
Console.WriteLine(ClassB XXX”);
}
}

/// <summary>
/// Class C
/// </summary>
public class ClassC : ClassB
{
public override void XXX()
{
base.XXX();
Console.WriteLine(ClassC XXX”);
}
}

/// <summary>
/// Class D
/// </summary>
public class ClassD : ClassC
{
public override void XXX()
{
Console.WriteLine(ClassD XXX”);
}
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
public class Program
{
private static void Main(string[] args)
{
ClassA a = new ClassB();
a.XXX();
ClassB b = new ClassC();
b.XXX();
Console.ReadKey();
}
}

Output

ClassA XXX
ClassB XXX
ClassA XXX
ClassB XXX
ClassC XXX
When we use the reserved keyword base, we can access the base class methods. Here no matter XXX is virtual or not, it will be treated as non virtual by the keyword base. Thus the base class XXX will always be called. The object aalready knows that XXX is virtual. When it reaches ClassB, it sees base.XXX() and hence it calls the XXX method ofClassA. But in the second case, it first goes to class ClassC, here it calls the base.XXX, i.e., the method XXX of classClassB, which in return invokes method XXX of class ClassA.

10. The Infinite Loop

/// <summary>
    /// Class A
    /// </summary>
    public class ClassA
    {
        public virtual void XXX()
        {
            Console.WriteLine("ClassA XXX");
        }
    }

/// <summary>
/// ClassB
/// </summary>
public class ClassB:ClassA
{
public override void XXX()
{
((ClassA)this).XXX();
Console.WriteLine(ClassB XXX”);
}
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
public class Program
{
private static void Main(string[] args)
{
ClassA a = new ClassB();
a.XXX();

}
}

Output

Error: {Cannot evaluate expression because the current thread is in a stack overflow state.}
In this kind of case, no casting will stop the infinite loop. Therefore even though this is being cast to a class ClassA, it will always call XXX from class ClassB and not ClassA. So we get no output.

11. Summary

Let’s summarize all the points to remember we got in the big article.
  1. In C#, a smaller object could be equated to a bigger object.
  2. The override modifier is needed as the derived class methods will get first priority and be called upon.
  3. These modifiers like new and override can only be used if the method in the base class is a virtualmethod. Virtual means that the base class is granting us permission to invoke the method from the derived class and not the base class. But, we have to add the modifier override if our derived class method has to be called.
  4. If the base class object declared the method virtual and the derived class used the modifier override, thederived class method will get called. Otherwise, the base class method will get executed. Therefore forvirtual methods, the data type created is decided at run time only.
  5. All the methods not marked with virtual are non virtual, and the method to be called is decided at compile time, depending upon the static data type of the object.
  6. An override method is a method that has the override modifier included on it. This introduces a new implementation of a method. We can’t use the modifiers such as newstatic or virtual along withoverride. But abstract is permitted.

12. Conclusion

Long article, my readers advice me to write short articles, but I can’t help myself. I write in a flow until and unless I clear the whole concept I do not wish to stop. My purpose is to share each and every detail in an easy manner, so that you start loving OOP. However in this article, I have tried to categorize the sections under different headings for the sake of readability.
In this article, we learnt the concept of run time polymorphism and inheritance. We covered most of the scenarios by doing hands-on lab. We’ll be covering more topics in my upcoming articles. Feel free to write comments or queries. Do like my article and rate if it helped you by any means, that will make me happy. Happy coding.

Read more:

Other Series

My other series of articles:

For more informative articles visit my Blog.

For more technical articles you can reach out to CodeTeddy.
Advertisements

Diving in OOP (Part 2) : Polymorphism and Inheritance (Inheritance)


Introduction

In our first part of the article, we learned about different scenarios of method overloading and did lots of interesting hands on too. My article in the second part of the series will focus solely on inheritance concept in OOP. Let’s define Inheritance using some bullet points:

Roadmap

We still stick to our roadmap that we defined before starting the series for learning OOP:

Note: Each and every code snippet written in this article is tried and tested.

Inheritance in Action

OK. Let’s do some hands on. Create a console application and name it InheritanceAndPolymorphism. Add a class named ClassA and a class named ClassB, with the following code:
ClassA:

class ClassA
{

}

ClassB:

class ClassB
{
public int x = 100;
public void Display1()
{
Console.WriteLine(ClassB Display1″);
}
public void Display2()
{
Console.WriteLine(ClassB Display2″);
}
}

We see classClassA is empty and we added two methods in class ClassB, i.e. Display1 and Display2. We also have a variable declared and defined with a value 100.
Now in the main method of Program.cs, write the following code:

Program.cs

class Program
    {
        static void Main(string[] args)
        {

ClassA a = new ClassA();
a.Display1();
}
}

If we run the code, we immediately result in the compile time error.
 
Error'InheritanceAndPolymorphism.ClassA‘ does not contain a definition for ‘Display1‘ and no extension method ‘Display1‘ accepting a first argument of type ‘InheritanceAndPolymorphism.ClassA‘ could be found (are you missing a using directive or an assembly reference?)
i.e. Too obvious, we don’t have definition of Display1 method in ClassA, nor can we access the same method usingClassA instance because it is not derived from any such class like ClassB that contains Display1 method. The class ClassA does not contain any code or variable defined. An empty class does not throw any error as we are able to instantiate an object that looks like a (instance of ClassA). The error comes about because the class ClassA has no method called Display1. However the class ClassB has a method named Display1. Guess how fun it could be if we are allowed to access all the code of classB from ClassA itself.
Just derive the class ClassA from ClassB using : operator as code shown below:
ClassA:

class ClassA:ClassB
{

}

ClassB:

class ClassB
{
public int x = 100;
public void Display1()
{
Console.WriteLine(ClassB Display1″);
}
public void Display2()
{
Console.WriteLine(ClassB Display2″);
}
}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            ClassA a = new ClassA();
            a.Display1();
            Console.ReadKey();
        }
    }
And now run the code as it was, we get an output now.

Output

ClassB Display1
i.e. now ClassA can access the inherited public methods of ClassB. The error vanishes and the Display1 inClassB gets invoked. If after the name of a class we specify : ClassB i.e., the name of another class, a lot changes at once. ClassA is now said to have been derived from ClassB. What that means is all the code we wrote in ClassBcan now be accessed and used in ClassA. It is if we actually wrote all the code that is contained in ClassB in ClassA. If we had created an instance that looks like that of ClassB, everything that the instance could do, now an instance ofClassA can also do. But we have not written a line of code in ClassA. We are made to believe that ClassA has one variable x and two functions Display1 and Display2 as ClassB contains these two functions. Therefore, we enter
into the concepts of inheritance where ClassB is the base class, ClassA the derived class.
Let’s take another scenario. Suppose we get into a situation where ClassA also has a method of same name as of inClassB. Let’s define a method Derive1 in ClassA too, so our code for classA becomes:
class ClassA:ClassB
    {
        public void Display1()
        {
            System.Console.WriteLine("ClassA Display1");
        }
    }

ClassB:

class ClassB
{
public int x = 100;
public void Display1()
{
Console.WriteLine(ClassB Display1″);
}
public void Display2()
{
Console.WriteLine(ClassB Display2″);
}
}

Now if we run the application using the following code snippet for Program.cs class:
class Program
    {
        static void Main(string[] args)
        {
            ClassA a = new ClassA();
            a.Display1();
            Console.ReadKey();
        }
    }
The question is what will happen now? What will be the output? Will there be any output or any compilation error. Ok, let’s run it.
We get Output:
ClassA Display1
But did you notice one thing, we also got a warning when we run the code:
 
Warning: ‘InheritanceAndPolymorphism.ClassA.Display1()‘ hides inherited member ‘InheritanceAndPolymorphism.ClassB.Display1()‘. Use the new keyword if hiding was intended.
 
Point to remember: No one can stop a derived class to have a method with the same name already declared in its base class.
So, ClassA undoubtedly can contain Display1 method, that is already defined with the same name in ClassB.
When we invoke a.Display1(), C# first checks whether the class ClassA has a method named Display1. If it does not find it, it checks in the base class. Earlier Display1 method was only available in the base class ClassB and hence got executed. Here, since it is there in ClassA, it gets called from ClassA and not ClassB.
 
Point to remember: Derived classes get a first chance at execution, then the base class.
The reason for this is that the base class may have a number of methods and for various reasons, we may not be satisfied with what they do. We should have the full right to have our copy of the method to be called. In other words, the derived classes methods override the ones defined in the base class.
What happens if we call base class Display1 method too with base keyword in derived class, i.e., by usingbase.Display1(), so our ClassA code will be:
ClassA:

class ClassA:ClassB
{
public void Display1()
{
Console.WriteLine(ClassA Display1″);
base.Display1();
}
}

ClassB:

class ClassB
{
public int x = 100;
public void Display1()
{
Console.WriteLine(ClassB Display1″);
}
public void Display2()
{
Console.WriteLine(ClassB Display2″);
}
}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            ClassA a = new ClassA();
            a.Display1();
            Console.ReadKey();
        }
    }

Output

ClassA Display1 
ClassB Display1
We see here first our ClassA Display1 method is called and then ClassB Display1 method.
Now if you want the best of both the classes , you may want to call the base classes (ClassBDisplay1 first and then yours or vice versa. To achieve this, C# gives you a free keyword, called base. The keyword base can be used in any of the derived class. It means call the method off the base class. Thus base.Display1 will call the methodDisplay1 fromClassB the base class
of ClassA as defined earlier.
 
Point to remember: A reserved keyword named “base” can be used in derived class to call the base class method.
What if we call Display2 method from base class, with an instance of derived class ClassA?
/// <summary>
   /// ClassB: acting as base class 
   /// </summary>
   class ClassB
    {
        public int x = 100;
        public void Display1()
        {
            Console.WriteLine("ClassB Display1");
        }
        public void Display2()
        {
            Console.WriteLine("ClassB Display2");
        }
    }

/// <summary>
/// ClassA: acting as derived class
/// </summary>
class ClassA : ClassB
{
public void Display1()
{
Console.WriteLine(ClassA Display1″);
base.Display2();
}
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
class Program
{
static void Main(string[] args)
{
ClassA a = new ClassA();
a.Display1();
Console.ReadKey();
}
}

Output

In the above code, we only made just a small change, base.Display1 was replaced by base.Display2. In this particular scenario, method Display2 from the class ClassB gets called. Base is usually a very general purpose. It lets us access members of the base class from the derived class as explained earlier. We cannot use base in ClassBas ClassB is not derived from any class as per our code. So it’s done that the base keyword can only be used in derived classes?
Let’s take another case:
/// <summary>
   /// ClassB: acting as base class 
   /// </summary>
   class ClassB
    {
        public int x = 100;
        public void Display1()
        {
            Console.WriteLine("ClassB Display1");
        }
    }

/// <summary>
/// ClassA: acting as derived class
/// </summary>
class ClassA : ClassB
{
public void Display2()
{
Console.WriteLine(ClassA Display2″);
}
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
class Program
{
static void Main(string[] args)
{
ClassB b = new ClassB();
b.Display2();
Console.ReadKey();
}
}

Output

Error: ‘InheritanceAndPolymorphism.ClassB‘ does not contain a definition for ‘Display2‘ and no extension method ‘Display2‘ accepting a first argument of type ‘InheritanceAndPolymorphism.ClassB‘ could be found (are you missing a using directive or an assembly reference?)
 
Point to remember: Inheritance does not work backwards.
So we got an error. Since we see, ClassA is derived from ClassB, i.e., ClassB is base class. Therefore, classClassAcan use all the members of class ClassB. Inheritance does not have backwards compatibility, whatever membersClassA contains do not permeate upwards toClassB. When we tried to access Display2 method of classA from the instance of class ClassB, it cannot give it to class ClassB and thus an error occurs.
 
Point to remember: Except constructors and destructors, a class inherits everything from its base class .
If a class ClassC is derived from class ClassB, which in turn has been derived from class ClassA, then ClassC will inherit all the members declared in ClassB and also of ClassA. This is called transitive concept in inheritance. A derived class may inherit all the members of the base class but it cannot remove members off that base class. A derived class can however hide members of the base class by creating methods by the same name. The original member/method of the base class remains unmodified and unaffected by whatever happens in the derived class. It remains unchanged in the base class, i.e., simply not visible in the derived class.
A class member could be of two types, i.e. either a static member that directly belongs to a class or an instance member that is accessed through instance of that class and belongs to that particular instance only. Instance member is accessible only through the object of the class and not directly by the class. The default member declared in the class are nonstatic, we just have to make them static by using static keyword.
All classes derive from a common base class named object. So Object is the mother of all classes.
If we do not derive any class from any other class, it’s the responsibility of C# to add :object by itself to the class definition. Object is the only class that is not derived from any other class. It is the ultimate base class for all the classes.
Suppose ClassA is derived from ClassB as in our case, but ClassB is not derived from any class,
public class ClassB
    {
    }

public class ClassA : ClassB
{
}

C# automatically adds :object to ClassB, i.e., the code at compile time becomes:
public class ClassB:object
    {
    }

public class ClassA : ClassB
{
}

But as per theory, we say ClassB is the direct base class of ClassA, so the classes of ClassA are ClassB and object.
Let’s go for another case:
public class ClassW : System.ValueType
    {
    }

public class ClassX : System.Enum
{
}

public class ClassY : System.Delegate
{
}

public class ClassZ : System.Array
{
}

Here we have defined four classes, each derive from a built in class in C#, let’s run the code.
We get so many compile time errors.

Errors

'InheritanceAndPolymorphism.ClassW' cannot derive from special class 'System.ValueType'
'InheritanceAndPolymorphism.ClassX' cannot derive from special class 'System.Enum'
'InheritanceAndPolymorphism.ClassY' cannot derive from special class 'System.Delegate'
'InheritanceAndPolymorphism.ClassZ' cannot derive from special class 'System.Array'
Don’t be scared.
Did you notice the word special class. Our classes defined cannot inherit from special built in classes in C#.
Point to remember: In inheritance in C#, custom classes cannot derive from special built in c# classes likeSystem.ValueTypeSystem.EnumSystem.DelegateSystem.Array, etc.
One more case,
public class ClassW
    {
    }

public class ClassX
{
}

public class ClassY : ClassW, ClassX
{
}

In the above mentioned case, we see three classes, ClassWClassX and ClassYClassY is derived from ClassWand ClassX. Now if we run the code, what would we get?
Compile time Error: Class ‘InheritanceAndPolymorphism.ClassY‘ cannot have multiple base classes: ‘InheritanceAndPolymorphism.ClassW‘ and ‘ClassX‘.
So one more Point to remember: A class can only be derived from one class in C#. C# does not support multiple inheritance by means of class*.
*Multiple inheritance in C# can be accomplished by the use of Interfaces, we are not discussing about interfaces in this article.
We are not allowed to derive from more than one class, thus every class can have only one base class.
Another case:
Suppose we try to write code as below:
public class ClassW:ClassY
    {
    }

public class ClassX:ClassW
{
}

public class ClassY : ClassX
{
}

Code is quite readable and simple, ClassW is derived from ClassYClassX is derived from ClassW, and ClassY in turn is derived from ClassX. So no problem of multiple inheritance, our code should build successfully. Let’s compile the code. What do we get? Again a compile time error.
Error: Circular base class dependency involving ‘InheritanceAndPolymorphism.ClassX‘ and ‘InheritanceAndPolymorphism.ClassW‘.
 
Point to remember: Circular dependency is not allowed in inheritance in C#. ClassX is derived from ClassW which was derived from ClassY and ClassY was again derived from ClassX, which caused circular dependency in three classes, that is logically impossible.

Equalizing the Instances/Objects

Let’s directly start with a real case:
ClassB:
public class ClassB
    {
        public int b = 100;
    }

ClassA:

public class ClassA
{
public int a = 100;
}

Program.cs

/// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            ClassB classB = new ClassB();
            ClassA classA = new ClassA();
            classA = classB;
            classB = classA;
        }
    }
We are here trying to equate two objects or two instances of two different classes. Let’s compile the code,
We get compile time error:
 
Error
Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA'

Cannot implicitly convert type ‘InheritanceAndPolymorphism.ClassA’ to ‘InheritanceAndPolymorphism.ClassB’

 
InheritanceAndPolymorphism is the namespace that I used for my console application, so there is no need to be scared of that word, just ignore it.
C# works on rules, it will never allow you to equate objects of different independent classes to each other. Therefore, we cannot equate an object classA of ClassA to classB of ClassB or vice versa. No matter the classes contain similar structure and their variables are initialized to similar integer value, even if we do.
public class ClassB
    {
        public int a = 100;
    }

public class ClassA
{
public int a = 100;
}

I just changed int b ofClassB to int a. In this case too, to equate an object is not allowed and not possible.
C# is also very particular if it comes with dealing with data types.
There is however one way to do this. By this way which we’ll discuss, one of the errors will disappear. The only time we are allowed to equate dissimilar data types is only when we derive from them? Check out the code mentioned below. Let’s discuss this in detail, when we create an object of ClassB by declaring new, we are creating two objects at one go, one that looks like ClassB and the other that looks like object, i.e., derived from Object class (i.e. ultimate base class). All classes in C# are finally derived from object. Since ClassA is derived from ClassB, when we declare newClassA, we are creating 3 objects, one that looks like ClassB, one that looks like ClassA and finally that looks likeobject class.
public class ClassB
    {
        public int b = 100;
    }

public class ClassA:ClassB
{
public int a = 100;
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
public class Program
{
private static void Main(string[] args)
{
ClassB classB = new ClassB();
ClassA classA = new ClassA();
classA = classB;
classB = classA;
}
}

We just derived ClassA from ClassB, this is something we can do, we learned a lot about this in this article. Now compile the code, we get:
 
Error: Cannot implicitly convert type ‘InheritanceAndPolymorphism.ClassB‘ to ‘InheritanceAndPolymorphism.ClassA‘. An explicit conversion exists (are you missing a cast?)
Like I mentioned, C# is very particular about objects equating.
Thus when we write classA = classBclassA looks like ClassAClassB and object and as a looks like ClassB, there is a match at ClassB.Result? No error Smile | :) . Even though classB and classA have the same values, usingclassB we can only access the members of ClassB, even though had we used classA we could access ClassAalso. We have devalued the potency of classB. The error occurs at classA = classB, because the class ClassB is less/smaller than the class ClassA. The class ClassA has ClassB and more. We cannot have a larger class on the right and a smaller class on the left. classB only represents a ClassB whereas classA expects a ClassA which is aClassA andClassB.
 
Point to remember: We can only and only equate the dissimilar objects if they are derived from each other. We can equate an object of a base class to a derived class but not vice versa.
Another code snippet:
public class ClassB
    {
        public int b = 100;
    }

public class ClassA:ClassB
{
public int a = 100;
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
public class Program
{
private static void Main(string[] args)
{
ClassB classB = new ClassB();
ClassA classA = new ClassA();
classB=classA;
classA = (ClassA)classB;
}
}

Although we violated a C# rule of equating objects, we did not get any compiler error because of the cast we did to the object. A() is called a cast. Within the brackets, the name of the class is put. A cast basically proves to be a great leveller. When we intend to write classA = classB, C# expects the right hand side of the equal to be a classA, i.e., a ClassA instance. But it finds classB, i.e., a ClassB instance. So when we apply the cast, we actually try to convert instance of ClassB to instance of ClassA. This approach satisfies the rules of C# on only equating similar objects type. Remember it is only for the duration of the line that classB becomes a ClassA and not a ClassB.
Now, if we remove ClassB as a base class to class ClassA as in the following code, and try to typecast classA toClassB object.
public class ClassB
    {
        public int b = 100;
    }

public class ClassA // Removed ClassB as base class
{
public int a = 100;
}

/// <summary>
/// Program: used to execute the method.
/// Contains Main method.
/// </summary>
public class Program
{
private static void Main(string[] args)
{
ClassB classB = new ClassB();
ClassA classA = new ClassA();
classB = (ClassB)classA;
classA = (ClassA)classB;
}
}

Output

Error
Cannot convert type 'InheritanceAndPolymorphism.ClassA' to 'InheritanceAndPolymorphism.ClassB'
Cannot convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA'
*’InheritanceAndPolymorphism’: Namespace I used in my application, so ignore that.
So we see that casting only works if one of the two classes is derived from one another. We cannot cast any two objects to each other.
One last example:
/// <summary>
    /// Program: used to execute the method.
    /// Contains Main method.
    /// </summary>
    public class Program
    {
        private static void Main(string[] args)
        {
            int integerA = 10;
            char characterB = 'A';
            integerA = characterB;
            characterB = integerA;
        }
    }
We run the code.

Output

Error: Cannot implicitly convert type ‘int‘ to ‘char‘. An explicit conversion exists (are you missing a cast?)
Point to remember: We cannot implicitly convert an int to char, but char can be converted to int.

Conclusion

In this part of our article series, we learned about inheritance. We took various scenarios and practical examples back to back to understand the concept deeply. In my next article, we’ll be discussing about run time polymorphism. Inheritance plays a very important role in run time polymorphism.
Let’s list down all our points to remember:
  1. No one can stop a derived class to have a method with the same name already declared in its base class.
  2. Derived classes get a first chance at execution, then the base class.
  3. A reserved keyword named “base” can be used in derived class to call the base class method.
  4. Inheritance does not work backwards.
  5. Except constructors and destructors, a class inherits everything from its base class.
  6. In inheritance in C#, custom classes cannot derive from special built in C# classes like System.ValueType,System.EnumSystem.DelegateSystem.Array, etc.
  7. A class can only be derived from one class in C#. C# does not support multiple inheritance by means of class.
  8. Circular dependency is not allowed in inheritance in C#. ClassX is derived from ClassW which was derived from ClassY and ClassY was again derived from ClassX, which caused circular dependency in three classes, that is logically impossible.
  9. We can only and only equate the dissimilar objects if they are derived from each other. We can equate an object of a base class to a derived class but not vice versa.
  10. We cannot implicitly convert an int to char, but char can be converted to int.
You can read about compile time polymorphism in my first article of the series. Keep coding and learning. .

Read more:

Other Series

My other series of articles:

For more informative articles visit my Blog.

For more technical articles you can reach out to CodeTeddy.

Diving in OOP (Part 1) : Polymorphism and Inheritance(Early Binding/Compile Time Polymorphism).


Introduction

I have been writing a lot about advanced topics like MVC, Entity Framework, Repository Patterns etc, my priority always remains to cover the topic as a whole, so that a reader does not have to search for missing links anywhere else. This article will cover almost every OOPS concept that a novice/beginner developer may hunt for, and not only beginners, the article’s purpose is to be helpful to experienced professionals who may need to brush-up on their concepts or who prepare for interviews.
I will take the topics in a manner that we cover them in a simple, straightforward way giving code snippets as example wherever needed. We’ll take C# as our programming language throughout our readings.
We’ll play with tricky questions and not go for enough theory. For theory you can refer MSDN.
Pre-requisites
Since this is the first part of the series, my readers should have basic knowledge of C# and should be aware of OOP concepts and terminology.
Note: Each and every code snippet written in this article is tried and tested.

OOPS

1. What is OOPS and what is advantage of OOP?

OOP stands for “Object-Oriented Programming.” Remember, it’s OOP not OOPS,’S’ may stand for system, synopsis, structure etc. It is a programming approach entirely based on objects, instead of just functions and procedures like in procedural languages. It is like a programming language model organized around objects rather than “actions” and data rather than logic. An “object” in an OOP language refers to a specific type, or “instance,” of a class. Each object has a structure exactly similar to other objects in a class, but can have individual properties/values. An object can also invoke methods, specific to that object
OOP makes it easier for developers to structure and organize software programs. Individual objects can be modified without affecting other aspects of the program therefore it is also easier to update and change programs written in object-oriented languages. Since the nature of software programs have grown larger over the years, OOP has made developing these large programs more manageable and readable.

2. What are OOP Concepts?

Following are OOP concepts explained in brief, we’ll take the topics in detail.
  1. Data Abstraction: Data Abstraction is a concept in which the internal and superfluous details of the implementation of a logic is hidden from an end user(who is using the program) .A user can use any of the data and method from the class without knowing about how this is created or what is the complexity behind it. In terms of a real world example, when we drive a bike and change the gears we don’t have to care about how internally its working, like how liver is pulled or how chain is set.
  2. Inheritance: Inheritance is most popular Concept in OOP’s .This provides a developer an advantage called reusability of code. Suppose a class is written having functions with specific logic, then we can derive that class into our newly created class and we don’t have to write the logic again for derived class functions, we can use them as it is.
  3. Data Encapsulation: Wrapping up of member data and member functions of a class in a single unit is called encapsulation. The visibility of the member functions,data members is set via access modifiers used in class.
  4. Polymorphism: Poly means many and morphism means many function The Concepts Introduces in the form of Many behaviours of an object.
  5. Message Communication: Message Communication means when an object passes the call to method of class for execution.
OK, we covered lots of theory, now it’s time for action. I hope that will be interesting. We’ll cover the topics in a series as follows,
  1. Diving in OOP (Day 1): Polymorphism and Inheritance(Early Binding/Compile Time Polymorphism)
  2. Diving in OOP (Day 2): Polymorphism and Inheritance (Inheritance)
  3. Diving in OOP (Day 3): Polymorphism and Inheritance (Dynamic Binding/Run Time Polymorphism)
  4. Diving in OOP (Day 4): Polymorphism and Inheritance (All about Abstarct classes in C#)
  5. Diving in OOP (Day 5): All about access modifiers in C# (Public/Private/Protected/Internal/Sealed/Constants/Readonly Fields)
  6. Diving in OOP (Day 6): Understanding Enum in C# (A Practical Approach)
  7. Diving into OOP (Day 7): Properties in C# (A Practical Approach)
  8. Diving into OOP (Day 8): Indexers in C# (A Practical Approach)
  9. Diving into OOP (Day 9): Understanding Events in C# (An Insight)

3. Polymorphism:

In this article we will cover almost all the scenarios of compile type polymorphism, the use of params keyword in detail, and case study or hands on to different possible combinations of the thoughts coming to our mind while coding.

Method Overloading or Early Binding or Compile Time Polymorphism

  1. Let’s create a simple console application named InheritanceAndPolymorphism, and add a class namedOverload.cs and add three methods named DisplayOverload having varied parameters as follows,

    Overload.cs

    public class Overload
        {
            public void DisplayOverload(int a){
                System.Console.WriteLine("DisplayOverload " + a);
            }
            public void DisplayOverload(string a){
                System.Console.WriteLine("DisplayOverload " + a);
            }
            public void DisplayOverload(string a, int b){
                System.Console.WriteLine("DisplayOverload " + a + b);
            }
        }

    In the main method in Program.cs file, add the following code,

    Program.cs

    class Program
        {
            static void Main(string[] args)
            {
                Overload overload = new Overload();
                overload.DisplayOverload(100);
                overload.DisplayOverload("method overloading");
                overload.DisplayOverload("method overloading", 100);
                Console.ReadKey();
            }
        }
Now when you run the application, the output is,

Output

DisplayOverload 100
DisplayOverload method overloading
DisplayOverload method overloading100
The class Overload contains three methods named DisplayOverload, they only differ in the datatype of the parameters they consist of. In C# we can have methods with the same name, but the datatypes of their parameters should differ. This feature of C# is called method overloading. Therefore, we need not to remember lots of method names if a method differs in behavior, only providing different parameters to the methods can call a method individually.
Point to remember: C# recognizes the method by its parameters and not by its name.
A signature signifies the full name of the method. So the name of a method or its signature is the original method name + the number and data types of its individual parameters.
If we run project using following code,
public void DisplayOverload() { }
     public int DisplayOverload(){ }
We certainly get a compile time error as,
Error: Type ‘InheritanceAndPolymorphism.Overload’ already defines a member called ‘DisplayOverload’ with the same parameter types
Here we had two functions who differ only in the data type of the value that they return, but we got a compile time error, therefore, another point to remember comes,
 
Point to remember: The return value/parameter type of a method is never the part of method signature if the names of the methods are same. So this is not polymorphism.
If we run the project using following code,
static void DisplayOverload(int a)  {   }
public void DisplayOverload(int a) {   }
public void DisplayOverload(string a){  }
We again get a compile time error,
Error: Type ‘InheritanceAndPolymorphism.Overload’ already defines a member called ‘DisplayOverload’ with the same parameter types
Can you differentiate with the modification done in the above code, we now have two DisplayOverload methods, that accept an int (integer). The only difference is that one method is marked static. Here the signature of the methods will be considered same as modifiers such as static are also not considered to be a part of method signature.
 
Point to remember: Modifiers such as static are not considered as part of method signature.
If we run the program as per following code, considering the method signature is different now,
private void DisplayOverload(int a) {   }

private void DisplayOverload(out int a)
{
a = 100;
}

private void DisplayOverload(ref int a) { }

We again get a compile time error,
Error: Cannot define overloaded method ‘DisplayOverload’ because it differs from another method only on ref and out
The signature of a method not only consists of the data type of the parameter but also the type/kind of parameter such as ref or out etc. Method DisplayOverload takes an int with different access modifiers i.e. out/ref etc, the signature on each is different.
 
Point to remember: The signature of a method consists of its name, number and types of its formal parameters. The return type of a function is not part of the signature. Two methods can not have the same signature and also non-members cannot have the same name as members.

4. Role of Params Parameter in Polymorphism

A method can be called by four different types of parameters.
  1. pass by value,
  2. Pass by reference,
  3. As an output parameter,
  4. Using parameter arrays.
As explained earlier the parameter modifier is never the part of method signature. Now let’s focus on Parameter Arrays.
A method declaration means creating a separate declaration space in memory. So anything created will be lost at the end of the method.
Running following code,
public void DisplayOverload(int a, string a)  {   }

public void Display(int a)
{
string a;
}

Results in compile time error,
 
Error1: The parameter name ‘a’ is a duplicate
Error2: A local variable named ‘a’ cannot be declared in this scope because it would give a different meaning to ‘a’, which is already used in a ‘parent or current’ scope to denote something else
 
Point to remember: Parameter names should be unique. And also we can not have a parameter name and a declared variable name in the same function as same.
In the case of pass by value, the value of the variable is passed and in the case of ref and out, the address of the reference is passed.
When we run the following code,

Overload.cs

public class Overload
    {
        private string name = "Akhil";

public void Display()
{
Display2(ref name, ref name);
System.Console.WriteLine(name);
}

private void Display2(ref string x, ref string y)
{
System.Console.WriteLine(name);
x = Akhil 1″;
System.Console.WriteLine(name);
y = Akhil 2″;
System.Console.WriteLine(name);
name = Akhil 3″;
}
}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            Overload overload = new Overload();
            overload.Display();
            Console.ReadKey();
        }
    }
We get out put as,

Output

Akhil
Akhil 1
Akhil 2
Akhil3

We are allowed to pass the same ref parameter as many times as we want. In the method Display the string name has a value of Akhil. Then by changing the string x to Akhil1, we are actually changing the string name to Akhil1 as name is passed by reference. Variables x and name refer to the same string in memory. Changing one changes the other. Again changing y also changes name variable as they refer to the same string anyways. Thus variables x, y and name refer to the same string in memory.
When we run the following code,

Overload.cs

public class Overload
    {
        public void Display()
        {
            DisplayOverload(100, "Akhil", "Mittal", "OOP");
            DisplayOverload(200, "Akhil");
            DisplayOverload(300);
        }

private void DisplayOverload(int a, params string[] parameterArray)
{
foreach (string str in parameterArray)
Console.WriteLine(str + + a);
}
}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            Overload overload = new Overload();
            overload.Display();
            Console.ReadKey();
        }
    }
We get output,

Output

Akhil 100
Mittal 100
OOP 100
Akhil 200
We will often get into a scenario where we would like to pass n number of parameters to a method. Since C# is very particular in parameter passing to methods, if we pass an int where a string is expected, it immediately breaks down. But C# provides a mechanism for passing n number of arguments to a method,
we can achieve it with the help ofparams keyword.
 
Point to remember: This params keyword can only be applied to the last argument of the method. So the n number of parameters can only be at the end.
In the case of method DisplayOverload, the first argument has to be an integer, the rest can be from zero to an infinite number of strings.
If we add a method like ,
private void DisplayOverload(int a, params string[] parameterArray, int b) {  }
We get a compile time error as,
 
Error: A parameter array must be the last parameter in a formal parameter list
Thus is is proved that params keyword will be the last parameter in a method, this is already stated in the latest point to remember.

Overload.cs

public class Overload
    {
        public void Display()
        {
            DisplayOverload(100, 200, 300);
            DisplayOverload(200, 100);
            DisplayOverload(200);
        }

private void DisplayOverload(int a, params int[] parameterArray)
{
foreach (var i in parameterArray)
Console.WriteLine(i + + a);
}

}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            Overload overload = new Overload();
            overload.Display();
            Console.ReadKey();
        }
    }
When we run the code we get,
200 100
300 100
100 200
Therefore,
 
Point to Remember: C# is very smart to recognize if the penultimate argument and the params have the same data type.
The first integer is stored in the variable a, the rest are made part of the array parameterArray.
private void DisplayOverload(int a, params string[][] parameterArray)  {     }

private void DisplayOverload(int a, params string[,] parameterArray) { }

For the above written code, we again get a compile time error and a new point to remember as well,
 
Error:The parameter array must be a single dimensional array
Point to remember: same as error above.
The data type of the params argument must be a single dimensional array. Therefore [ ][ ]
is allowed but not [,]. We also not allowed to combine the params keyword with ref or out.

Overload.cs

public class Overload
    {
        public void Display()
        {
            string[] names = {"Akhil", "Ekta", "Arsh"};
            DisplayOverload(3, names);
        }

private void DisplayOverload(int a, params string[] parameterArray)
{
foreach (var s in parameterArray)
Console.WriteLine(s + + a);
}

}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            Overload overload = new Overload();
            overload.Display();
            Console.ReadKey();
        }
    }

Output

Akhil 3
Ekta 3
Arsh 3
We are, therefore, allowed to pass a string array instead of individual strings as arguments. Here, names is a string array which has been initialized using the short form. Internally when we call the function DisplayOverload, C# converts the string array into individual strings.

Overload.cs

public class Overload
    {
        public void Display()
        {
           string [] names = {"Akhil","Arsh"};
           DisplayOverload(2, names, "Ekta");
        }

private void DisplayOverload(int a, params string[] parameterArray)
{
foreach (var str in parameterArray)
Console.WriteLine(str + + a);
}

}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            Overload overload = new Overload();
            overload.Display();
            Console.ReadKey();
        }
    }

Output

Error: The best overloaded method match for ‘InheritanceAndPolymorphism.Overload.DisplayOverload(int, params string[])’ has some invalid arguments
Error:Argument 2: cannot convert from ‘string[]’ to ‘string’
So, we got two errors. 
For the above mentioned code, C# does not permit mix and match. We assumed that the last string “Ekta” would be added to the array of strings names or convert names to individual strings and then add the string “Ekta” to it. Quite logical.
Internally before calling the function DisplayOverload, C# accumulates all the individual parameters and converts them into one big array for the params statement.

Overload.cs

public class Overload
    {
        public void Display()
        {
            int[] numbers = {10, 20, 30};
            DisplayOverload(40, numbers);
            Console.WriteLine(numbers[1]);
        }

private void DisplayOverload(int a, params int[] parameterArray)
{
parameterArray[1] = 1000;
}

}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            Overload overload = new Overload();
            overload.Display();
            Console.ReadKey();
        }
    }

Output

1000
We see that the output produced is the proof of concept. The member parameterArray[1] of array has an initial value of 20 and in the method DisplayOverload, we changed it to 1000. So the original value changes, this shows that the array is given to the method DisplayOverload, Hence proved.

Overload.cs

public class Overload
    {
        public void Display()
        {
            int number = 102;
            DisplayOverload(200, 1000, number, 200);
            Console.WriteLine(number);
        }

private void DisplayOverload(int a, params int[] parameterArray)
{
parameterArray[1] = 3000;
}

}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            Overload overload = new Overload();
            overload.Display();
            Console.ReadKey();
        }
    }

Output

102
In the above mentioned scenario C# creates an array containing 1000 102 and 200. We now change the second member of array to 3000 which has nothing to do with the variable number. As DisplayOverload has no knowledge of number, so how can DisplayOverload change the value of the int number? Therefore it remains the same.

Overload.cs

public class Overload
    {
        public void Display()
        {
            DisplayOverload(200);
            DisplayOverload(200, 300);
            DisplayOverload(200, 300, 500, 600);
        }

private void DisplayOverload(int x, int y)
{
Console.WriteLine(The two integers “ + x + + y);
}

private void DisplayOverload(params int[] parameterArray)
{
Console.WriteLine(parameterArray”);
}

}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            Overload overload = new Overload();
            overload.Display();
            Console.ReadKey();
        }
    }

Output

parameterArray
The two integers 200 300
parameterArray
Now we’ll talk about method overloading. C# is extremely talented though partial. It does not appreciate the paramsstatement and treats it as a stepchild. When we invoke DisplayOverload only with one integer, C# can only call theDisplayOverload that takes a params as a parameter as it matches only one int. An array can contain one member too. The fun is with the DisplayOverload that is called with two ints now. So here we have a dilemma. C# can call theparams DisplayOverload or DisplayOverload with the two ints. As discussed earlier, C# treats the params as a second class member and therefore chooses the DisplayOverload with two ints. When there are more than two ints like in the third method call, C# is void of choice but to grudgingly choose the DisplayOverload with the params. C# opts for the params as a last resort before flagging an error.
Now a bit tricky example, yet important,

Overload.cs

public class Overload
    {
        public static void Display(params object[] objectParamArray)
        {
            foreach (object obj in objectParamArray)
            {
                Console.Write(obj.GetType().FullName + " ");
            }
            Console.WriteLine();

}
}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            object[] objArray = { 100, "Akhil", 200.300 };
            object obj = objArray;
            Overload.Display(objArray);
            Overload.Display((object)objArray);
            Overload.Display(obj);
            Overload.Display((object[])obj);
            Console.ReadKey();

}
}

Output

System.Int32 System.String System.Double
System.Object[]
System.Object[]
System.Int32 System.String System.Double
In the first instance we are passing the method Display an array of object that looks like object. Since all the classes are derived from a common base class object, we can do that. The method Display gets an array of objectsobjectParamArray. In the foreach object class has a method named GetType that returns an object that looks like Type, which too has a method named FullName that returns the name of the type. Since three different types displayed. In the second method call of Display we are casting objArray to an object. Since there is no conversion available from converting an object to an object array i.e. object [ ], so only a one element object [ ] is created. It’s the same case in the third invocation and the last explicitly casts to an object array.
For proof of concept,

Overload.cs

public class Overload
    {
        public static void Display(params object[] objectParamArray)
        {
            Console.WriteLine(objectParamArray.GetType().FullName);
            Console.WriteLine(objectParamArray.Length);
            Console.WriteLine(objectParamArray[0]);

}
}

Program.cs

class Program
    {
        static void Main(string[] args)
        {
            object[] objArray = { 100, "Akhil", 200.300 };
            Overload.Display((object)objArray);
            Console.ReadKey();
        }
    }

Output

System.Object[]
1
System.Object[]

5. Conclusion

In this article of our Diving in OOP series we learnt about compile time polymorphism, it is also called early binding or method overloading. We catered most of the scenarios specific to polymorphism.We also learned about the use of powerful params keyword and its use in polymorphism.
To sum up lets list down all the point to remembers once more,
  1. C# recognizes the method by its parameters and not by its name.
  2. The return value/parameter type of a method is never the part of method signature if the names of the methods are same. So this is not polymorphism.
  3. Modifiers such as static are not considered as part of method signature.
  4. The signature of a method consists of its name, number and types of its formal parameters. The return type of a function is not part of the signature. Two methods can not have the same signature and also non-members cannot have the same name as members.
  5. Parameter names should be unique. And also we can not have a parameter name and a declared variable name in the same function as same.
  6. In case of pass by value, the value of the variable is passed and in the case of ref and out, the address of the reference is passed.
  7. This params keyword can only be applied to the last argument of the method.So the n number of parameters can only be at the end.
  8. C# is very smart to recognize if the penultimate argument and the params have the same data type.
  9. Parameter array must be a single dimensional array.
In upcoming articles we’ll cover topics in the same fashion.  Happy Coding.

Read more:

Other Series

My other series of articles:

For more informative articles visit my Blog.

For more technical articles you can reach out to CodeTeddy.