Diving into OOP (Day 5): All About C# Access Modifiers (Public/Private/Protected/Internal/Sealed/Constants/Static and Readonly Fields)


Introduction

Thanks to my readers for their tremendous support which has motivated me to continue this OOP series further.
We have already covered almost all the aspects of Inheritance and Polymorphism in C#. My article will highlight almost all the aspects/scenarios of access modifiers in C#. We’ll learn by doing hands on lab and not only by theory. We’ll cover my favourite topic Constants in a very different manner by categorizing the sections in the form of “Labs”. My effort in this article will be to cover each and every concept of the related topic, so that at the end of the article, we can confidently say that we know “All about access modifiers in C#”. Just dive into OOP.

Pre-requisites

I expect that readers of this article should have very basic knowledge of C#. The reader should only know the definition of access modifiers. Last but not the least, as always, I wish that my readers should enjoy reading this article.

Roadmap

Let’s recall our road map:

Access Modifiers

Let us take the definition from Wikipedia this time:

“Access modifiers (or access specifiers) are keywords in object-oriented languages that set the accessibility of classes, methods, and other members. Access modifiers are a specific part of programming language syntax used to facilitate the encapsulation of components.”

Like the definition says, we can control the accessibility of our class methods and members through access modifiers, let us understand this in detail by taking every access modifier one by one.

Public, Private, Protected at Class Level

Whenever we create a class, we always want to have the scope to decide who can access certain members of the class. In other words, we would sometimes need to restrict access to the class members. The one thumb rule is that members of a class can freely access each other. A method in one class can always access another method of the same class without any restrictions. When we talk about the default behavior, the same class is allowed complete access but no else is provided access to the members of the class. The default access modifier is private for class members.
Point to remember: The default access modifier is private for class members.
Let’s do some hands on lab. Just open your Visual Studio and add a console application in C# namedAccessModifiers. You’ll get a Program.cs class file by default. In the same file, add a new class named Modifiersand add the following code to it:
using System;

namespace AccessModifiers
{
class Modifiers
{
static void AAA()
{
Console.WriteLine(Modifiers AAA”);
}

public static void BBB()
{
Console.WriteLine(Modifiers BBB”);
AAA();
}
}

class Program
{
static void Main(string[] args)
{
Modifiers.BBB();
}
}
}

So, your Program.cs file becomes like shown in the above code snippet. We added a class Modifiers and two staticmethods AAA and BBB. Method BBB is marked as public. We call the method BBB from Main method.The method is called directly by the class name because it is marked static.
When we run the application, we get the output as follows:

Output

Modifiers BBB
Modifiers AAA
 
BBB is marked public and so anyone is allowed to call and run it. Method AAA is not marked with any access modifier which automatically makes it private, that is the default. The private modifier has no effect on members of the same class and so method BBB is allowed to call method AAA. Now this concept is called member access.
Modify the Program class and try to access AAA as:
class Program
    {
static void Main(string[] args)
        {
            Modifiers.AAA();
            Console.ReadKey();
        }
    }

Output

'AccessModifiers.Modifiers.AAA()' is inaccessible due to its protection level
So , since methodAAA is private, therefore no one else can have access to it except Modifiers class.
Note: Each and every code snippet written in this article is tried and tested.
 
Modifiers
Now mark the AAA method as protected, our class looks like:
class Modifiers
    {
protected static void AAA()
        {
            Console.WriteLine("Modifiers AAA");
        }

public static void BBB()
{
Console.WriteLine(Modifiers BBB”);
AAA();
}
}

Program

class Program
    {
static void Main(string[] args)
        {
            Modifiers.AAA();
            Console.ReadKey();
        }
    }

Output

'AccessModifiers.Modifiers.AAA()' is inaccessible due to its protection level
Again the same output. We cannot access the method AAA even after we introduced a new modifier namedprotected. But BBB can access AAA method because it lies in the same class.

Modifiers in Inheritance

Let’s add one more class and make a relation of base and derived class to our existing class and add one more method to our base class. So our class structure will look something like this:

Modifiers Base Class

class ModifiersBase
    {
static void AAA()
        {
            Console.WriteLine("ModifiersBase AAA");
        }
public static void BBB()
        {
            Console.WriteLine("ModifiersBase BBB");
        }
protected static void CCC()
        {
            Console.WriteLine("ModifiersBase CCC");
        }
    }

Modifiers Derive Class

class ModifiersDerived:ModifiersBase
    {
public static void XXX()
        {
            AAA();
            BBB();
            CCC();
        }
    }

Program Class

class Program
    {
static void Main(string[] args)
        {
            ModifiersDerived.XXX();
            Console.ReadKey();
        }
    }

Output

'AccessModifiers.ModifiersBase.AAA()' is inaccessible due to its protection level
Now in this case, we are dealing with derived class. Whenever we mark a method with the specifier, protected, we are actually telling C# that only derived classes can access that method and no one else can. Therefore in method XXX, we can call CCC because it is marked protected, but it cannot be called from anywhere else including Main function. The method AAA is made private and can be called only from the class ModifiersBase. If we remove AAA from method XXX, the compiler will give no error.
Therefore, now we are aware of three important concepts. Private means only the same class has access to the members, public means everybody has access and protected lies in between where only derived classes have access to the base class method.
All the methods for example reside in a class. The accessibility of that method is decided by the class in which it resides as well as the modifiers on the method. If we are allowed an access to a member, then we say that the member is accessible, else it is inaccessible.

Internal Modifier at Class Level

Let’s take one another scenario. Create a class library with a name “AccessModifiersLibrary” in your Visual Studio. Add a class named ClassA in that class library and mark the class as internal, the code will be as shown below:
AccessModifiersLibrary.ClassA:

namespace AccessModifiersLibrary
{
internal class ClassA
{
}
}

Now compile the class, and leave it. Its DLL will be generated in ~\AccessModifiersLibrary\bin\Debug folder.
Now in your console application, “AccessModifiers” i.e. created earlier. Add the reference ofAccessModifiersLibrary library by adding its compiled DLL as a reference to AccessModifiers.
In Program.cs of AccessModifiers console application, modify the Program class like shown below:

AccessModifiers.Program

using AccessModifiersLibrary;

namespace AccessModifiers
{
class Program
{
static void Main(string[] args)
{
ClassA classA;
}
}
}

And compile the code.

Output

Compile time error: 'AccessModifiersLibrary.ClassA' is inaccessible due to its protection level
We encountered this error because the access specifier internal means that we can only access ClassA fromAccessModifiersLibrary.dll and not from any other file or code. Internal modifier means that access is limited to current program only. So try never to create a component and mark the class internal as no one would be able to use it.
And what if we remove the field internal from ClassA, will the code compile? i.e.,

AccessModifiersLibrary.ClassA

namespace AccessModifiersLibrary
{
class ClassA
    {
    }
}

AccessModifiers.Program

using AccessModifiersLibrary;

namespace AccessModifiers
{
class Program
{
static void Main(string[] args)
{
ClassA classA;
}
}
}

Output

Compile time error: 'AccessModifiersLibrary.ClassA' is inaccessible due to its protection level
We again got the same error. We should not forget that by default if no modifier is specified, the class is internal. So our class ClassA is internal by default even if we do not mark it with any access modifier, so the compiler results remain the same.
Had the class ClassA been marked public, everything would have gone smooth without any error.
Point to remember: A class marked as internal can only be have its access limited to the current assembly only.

Namespaces with Modifiers

Let’s for fun, mark a namespace of AccessModifiers class library as public in Program class:

Program

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

}
}
}

Compile the application.

Output

Compile time error: A namespace declaration cannot have modifiers or attributes
 
Point to remember: Namespaces as we see by default can have no accessibility specifiers at all. They are by defaultpublic and we cannot add any other access modifier including public again too.

Private Class

Let’s do one more experiment and mark the class Program as private, so our code becomes:
namespace AccessModifiers
{
private class Program
    {
static void Main(string[] args)
        {

}
}
}

Compile the code.

Output

Compile time error: Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal
Point to remember: A class can only be public or internal. It cannot be marked as protected or private. The default is internal for the class.
Access modifiers for the members of the class:
Now here is a big statement, that the members of a class can have all the above explained access modifiers, but default modifier is private.
Point to remember: Members of a class can be marked with all the access modifiers, and the default access modifier isprivate.
What if we want to mark a method with two access modifiers?
namespace AccessModifiers
{
public class Program
    {
static void Main(string[] args)
        {
        }

public private void Method1()
{

}
}
}

Compile the code.

Output

Compile time error: More than one protection modifier
Therefore, we can’t mark a member with more than one access modifier often. But there are such scenarios too, we’ll cover them in next sections. Already defined types like int and object have no accessibility restrictions. They can be used anywhere and everywhere.

Internal Class and Public Method

Create a class library with a class named ClassA marked internal and have a public method MethodClassA(), as:
namespace AccessModifiersLibrary
{
internal class ClassA
    {
public void MethodClassA(){}
    }
}
Add the reference of class library to our console application. Now in Program.cs of console application, try to access that method MethodClassA of ClassA.

Program

using AccessModifiersLibrary;

namespace AccessModifiers
{
public class Program
{
public static void Main(string[] args)
{
ClassA classA = new ClassA();
classA.MethodClassA();
}
}
}

Output

Compile time errors:
'AccessModifiersLibrary.ClassA' is inaccessible due to its protection level
The type 'AccessModifiersLibrary.ClassA' has no constructors defined
'AccessModifiersLibrary.ClassA' is inaccessible due to its protection level
'AccessModifiersLibrary.ClassA' does not contain a definition for 'MethodClassA' and
no extension method 'MethodClassA' accepting a first argument of type 'AccessModifiersLibrary.ClassA'
could be found (are you missing a using directive or an assembly reference?)
So many errors. The errors are self explanatory though. Even the method MethodClassA of ClassA is public, it could not be accessed in Program class due to protection level of ClassA, i.e. internal. The type enclosing the method MethodClassA is internal, so no matter if the method is marked public, we cannot access it in any other assembly.

Public Class and Private Method

Let’s make the class ClassA as public and method as private:
AccessModifiersLibrary.ClassA:

namespace AccessModifiersLibrary
{
public class ClassA
{
private void MethodClassA(){}
}
}

Program

using AccessModifiersLibrary;

namespace AccessModifiers
{
public class Program
{
public static void Main(string[] args)
{
ClassA classA = new ClassA();
classA.MethodClassA();
}
}
}

Output on compilation

'AccessModifiersLibrary.ClassA' does not contain a definition
for 'MethodClassA' and no extension method 'MethodClassA' accepting a first argument
of type 'AccessModifiersLibrary.ClassA' could be found (are you missing a using directive or an assembly reference?)
Now we marked our class Public, still can’t access the private method. So for accessing a member of the class, the access modifier of class as well as method is very important.
 
Note: Each and every code snippet written in this article is tried and tested.

Public Class and Internal Method

Make ClassA as public and MethodClassA as internal:
AccessModifiersLibrary.ClassA:

namespace AccessModifiersLibrary
{
public class ClassA
{
Internal void MethodClassA(){}
}
}

Program

using AccessModifiersLibrary;

namespace AccessModifiers
{
public class Program
{
public static void Main(string[] args)
{
ClassA classA = new ClassA();
classA.MethodClassA();
}
}
}

Output on compilation

'AccessModifiersLibrary.ClassA' does not contain a definition for 'MethodClassA' and no extension
method 'MethodClassA' accepting a first argument of type 'AccessModifiersLibrary.ClassA' could be
found (are you missing a using directive or an assembly reference?)
So an internal marked member means that no one from outside that DLL can access the member.

Protected Internal

In the class library, make three classes ClassAClassB and ClassC, and place the code somewhat like this:
namespace AccessModifiersLibrary
{
public class ClassA
    {
protected internal void MethodClassA()
        {

}
}

public class ClassB:ClassA
{
protected internal void MethodClassB()
{
MethodClassA();
}
}

public class ClassC
{
public void MethodClassC()
{
ClassA classA=new ClassA();
classA.MethodClassA();
}
}
}

And in Program class in our console application, call the MethodClassC of ClassC.

Program

using AccessModifiersLibrary;

namespace AccessModifiers
{
public class Program
{
public static void Main(string[] args)
{
ClassC classC=new ClassC();
classC.MethodClassC();
}
}
}

Compiler output

The code successfully compiles with no error.
 
Protected internal modifier indicates two things, that either the derived class or the class in the same file can have access to that method, therefore in the above mentioned scenario, the derived class ClassB and the class in the same file, i.e., ClassC can access that method of ClassA marked as protected internal.
 
Point to rememberProtected internal means that the derived class and the class within the same source code file can have access.

Protected Member

In our Program.cs in console application, place the following code:
namespace AccessModifiers
{
class AAA
    {
protected int a;
void MethodAAA(AAA aaa,BBB bbb)
        {
            aaa.a = 100;
            bbb.a = 200;
        }
    }
class BBB:AAA
     {
void MethodBBB(AAA aaa, BBB bbb)
         {
             aaa.a = 100;
             bbb.a = 200;
         }
     }
public class Program
    {
public static void Main(string[] args)
        {
        }
    }
}

Compiler Output

Cannot access protected member 'AccessModifiers.AAA.a' via a qualifier of type 'AccessModifiers.AAA';
the qualifier must be of type 'AccessModifiers.BBB' (or derived from it)
Class AAA is containing a protected member, i.e., a. But to the same class, no modifiers make sense. However as isprotected, in the derived class method MethodBBB, we cannot access it through AAA as aaa.a gives us an error. However bbb which looks like BBB does not give an error. To check this out, comment out the line aaa.a=100 inMethodBBB (). This means that we cannot access the protected members from an object of the base class, but from the objects of derived class only. This is in spite of the fact that is a member of AAA i.e. the base class. Even so, we still cannot access it. Also we cannot access from the method Main.

Accessibility Priority in Inheritance

Program

namespace AccessModifiers
{
class AAA
    {

}
public class BBB:AAA
{

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

Compiler Output

Compile time error: Inconsistent accessibility: base class 'AccessModifiers.AAA' is less accessible than class 'AccessModifiers.BBB'
The error again gives us one more point to remember.
 
Point to remember: In between public and internalpublic always allows greater access to its members.
The class AAA is by default marked internal and BBB that derives from AAA is made public explicitly. We got an error as the derived class BBB has to have an access modifier which allows greater access than the base class access modifier. Here internal seems to be more restrictive than public.
But if we reverse the modifiers to both the classes i.e. ClassA marked as public and ClassB internal or default, we get rid of the error.
 
Point to remember: The base class always allows more accessibility than the derived class.
Another scenario:

Program

namespace AccessModifiers
{
class AAA
    {

}
public class BBB
{
public AAA MethodB()
{
AAA aaa= new AAA();
return aaa;
}
}
public class Program
{
public static void Main(string[] args)
{
}
}
}

Compiler output

Inconsistent accessibility: return type 'AccessModifiers.AAA' is less accessible than method 'AccessModifiers.BBB.MethodB()'
Here the accessibility of AAA is internal which is more restrictive than public. The accessibility of method MethodBis public which is more than that of the typeAAA. Now the error occurred because return values of a method must have greater accessibility than that of the method itself, which is not true in this case.
 
Point to remember: The return values of a method must have greater accessibility than that of the method itself.

Program

namespace AccessModifiers
{
class AAA
    {

}
public class BBB
{
public AAA aaa;
}
public class Program
{
public static void Main(string[] args)
{
}
}
}

Compiler Output

Inconsistent accessibility: field type 'AccessModifiers.AAA' is less accessible than field 'AccessModifiers.BBB.aaa'
Now rules are the same for everyone. The class AAA or data type aaa is internalaaa field is public which makes it more accessible than AAA which is internal. So we got the error.
Change the code to:
namespace AccessModifiers
{
class AAA
    {

}
public class BBB
{
AAA a;
}
public class Program
{
public static void Main(string[] args)
{
}
}
}

The output compilation results in no error.
We learnt a lot about these access modifiers like publicprivateprotectedinternalprotected internal. We also learnt about their priority of access and usage, let’s summarize their details in a tabular format for revision. Later, we’ll move to other types as well.
Tables taken from MSDN:
Declared accessibility Meaning
public Access is not restricted.
protected Access is limited to the containing class or types derived from the containing class.
internal Access is limited to the current assembly.
protected internal Access is limited to the current assembly or types derived from the containing class.
private Access is limited to the containing type.
“Only one access modifier is allowed for a member or type, except when you use the protected internalcombination.
Access modifiers are not allowed on namespaces. Namespaces have no access restrictions.
Depending on the context in which a member declaration occurs, only certain declared accessibilities are permitted. If no access modifier is specified in a member declaration, a default accessibility is used.
Top-level types, which are not nested in other types, can only have internal or public accessibility. The default accessibility for these types is internal.
Nested types, which are members of other types, can have declared accessibilities as indicated in the following table.”
Members of Default member accessibility Allowed declared accessibility of the member
enum Public None
class Private public
protected
internal
private
protected internal
interface Public None
struct Private public
internal
private

Sealed Classes

Sealed” is a special class of access modifier in C#. If a class is marked as sealed, no other class can derive from thatsealed class. In other words, a class marked as sealed can’t act as a base class to any other class.

Program

namespace AccessModifiers
{
sealed class AAA
    {

}
class BBB:AAA
{

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

Compiler Output

'AccessModifiers.BBB': cannot derive from sealed type 'AccessModifiers.AAA'
Hence proved.
 
Point to remember: A class marked sealed can’t act as a base class to any other class.
Access the members of sealed class.

Program

using System;

namespace AccessModifiers
{
sealed class AAA
{
public int x = 100;
public void MethodA()
{
Console.WriteLine(Method A in sealed class”);
}
}
public class Program
{
public static void Main(string[] args)
{
AAA aaa=new AAA();
Console.WriteLine(aaa.x);
aaa.MethodA();
Console.ReadKey();
}
}
}

Compiler Output

100
Method A in sealed class
So, as we discussed, the only difference between a sealed and a non sealed class is that the sealed class cannot be derived from. A sealed class can contain variables, methods, properties like a normal class do.
 
Point to remember: Since we cannot derive from sealed classes, the code from the sealed classes cannot be overridden.
 
Note: Each and every code snippet written in this article is tried and tested.

Constants

Lab1

Our Program class in the console application.

Program

public class Program
    {
private const int x = 100;
public static void Main(string[] args)
        {
            Console.WriteLine(x);
            Console.ReadKey();
        }
    }

Output

100
We see, a constant marked variable or a const variable behaves like a member variable in C#. We can provide it an initial value and can use it anywhere we want.
 
Point to remember: We need to initialize the const variable at the time we create it. We are not allowed to initialize it later in our code or program.

Lab2

using System;

namespace AccessModifiers
{
public class Program
{
private const int x = y + 100;
private const int y = z – 10;
private const int z = 300;

public static void Main(string[] args)
{
System.Console.WriteLine({0} {1} {2}”,x,y,z);
Console.ReadKey();
}
}
}

Can you guess the output? What? Is it a compiler error?

Output

390 290 300
Shocked? A constant field can no doubt depend upon another constant. C# is very smart to realize that to calculate the value of variable marked const, it first needs to know the value of y variable. y’s value depends upon anotherconst variable z, whose value is set to 300. Thus C# first evaluates to 300 then becomes 290 i.e. z -1 and finally x takes on the value of y i.e. 290 + 100 resulting in 390.

Lab3

Program

using System;

namespace AccessModifiers
{
public class Program
{
private const int x = y + 100;
private const int y = z – 10;
private const int z = x;

public static void Main(string[] args)
{
System.Console.WriteLine({0} {1} {2}”,x,y,z);
Console.ReadKey();
}
}
}

Output

The evaluation of the constant value for 'AccessModifiers.Program.x' involves a circular definition
We just assigned z=x from our previous code, and it resulted into error. The value of const x depends upon y, and yin turn depends upon value of z, but we see value depends upon as is assigned directly to z, it results in a circular dependency.
 
Point to remember: Like classes, const variables cannot be circular, i.e., they cannot depend on each other.

Lab4

const is a variable whose value once assigned cannot be modified, but its value is determined at compile time only.
using System;

namespace AccessModifiers
{
public class Program
{
public const ClassA classA=new ClassA();
public static void Main(string[] args)
{
}
}

public class ClassA
{

}
}

Output

Compile time error: 'AccessModifiers.Program.classA' is of type 'AccessModifiers.ClassA'.
A const field of a reference type other than string can only be initialized with null.
 
Point to remember: A const field of a reference type other than string can only be initialized with null.
If we assign the value to null in Program class:
using System;

namespace AccessModifiers
{
public class Program
{
public const ClassA classA=null;
public static void Main(string[] args)
{
}
}

public class ClassA
{

}
}

Then the error will vanish. The error disappears as we now initialize classA to an object which has a value that can be determined at compile time i.e., null. We can never change the value of classA, so it will always be null. Normally, we do not have consts as classA reference type as they have value only at runtime.
 
Point to remember: One can only initialize a const variable to a compile time value, i.e., a value available to the compiler while it is executing.
new() actually gets executed at runtime and therefore does not get value at compile time. So this results in an error.

Lab5

ClassA

public class ClassA
    {
public const int aaa = 10;
    }

Program

public class Program
    {
public static void Main(string[] args)
        {
            ClassA classA=new ClassA();
            Console.WriteLine(classA.aaa);
            Console.ReadKey();
        }
    }

Output

Compile time error: Member 'AccessModifiers.ClassA.aaa'
cannot be accessed with an instance reference; qualify it with a type name instead
 
Point to remember: A constant by default is static and we can’t use the instance reference, i.e., a name to reference a const. A const has to be static as no one will be allowed to make any changes to a const variable.
Just mark the const as static.
using System;

namespace AccessModifiers
{
public class ClassA
{
public static const int aaa = 10;
}

public class Program
{
public static void Main(string[] args)
{
ClassA classA=new ClassA();
Console.WriteLine(classA.aaa);
Console.ReadKey();
}
}
}

Output

Compile time error: The constant 'AccessModifiers.ClassA.aaa' cannot be marked static
C# tells us frankly that a field i.e. already static by default cannot be marked as static.
Point to remember: A const variable cannot be marked as static.

Lab6

using System;

namespace AccessModifiers
{
public class ClassA
{
public const int xxx = 10;
}

public class ClassB:ClassA
{
public const int xxx = 100;
}

public class Program
{
public static void Main(string[] args)
{
Console.WriteLine(ClassA.xxx);
Console.WriteLine(ClassB.xxx);
Console.ReadKey();
}
}
}

Output

10
100
Compiler Warning: 'AccessModifiers.ClassB.xxx' hides inherited
member 'AccessModifiers.ClassA.xxx'. Use the new keyword if hiding was intended.
We can always create a const with the same name in the derived class as another const in the base class. The constvariable of class ClassB xxx will hide the const xxx in class ClassA for the class ClassB only.

Static Fields

Point to remember: A variable in C# can never have an uninitialized value.
Let’s discuss this in detail.

Lab1

Program

using System;

namespace AccessModifiers
{
public class Program
{
private static int x;
private static Boolean y;
public static void Main(string[] args)
{
Console.WriteLine(x);
Console.WriteLine(y);
Console.ReadKey();
}
}
}

Output

0
False
 
Point to rememberStatic variables are always initialized when the class is loaded first. An int is given a default value of zero and a bool is given a default to False.

Lab2

Program

using System;

namespace AccessModifiers
{
public class Program
{
private int x;
private Boolean y;
public static void Main(string[] args)
{
Program program=new Program();
Console.WriteLine(program.x);
Console.WriteLine(program.y);
Console.ReadKey();
}
}
}

Output

0
False
 
Point to remember: An instance variable is always initialized at the time of creation of its instance.
An instance variable is always initialized at the time of creation of its instance. The keyword new will create an instance of the class Program. It will allocate memory for each of the non static, i.e. instance variables and then initialize each of them to their default values as well.

Lab3

Program

using System;

namespace AccessModifiers
{
public class Program
{
private static int x = y + 10;
private static int y = x + 5;
public static void Main(string[] args)
{
Console.WriteLine(Program.x);
Console.WriteLine(Program.y);
Console.ReadKey();
}
}
}

Output

10
15
Output is self explanatory. C# always initializes static variables to their initial value after creating them. Variables xand are therefore given a default of zero value. C# now realizes that these variables declared need to be assigned some values. C# does not read all the lines at once but only one at a time. It will now read the first line and as the variable y has a value of 0, so will get a value of 10. Then at the next line, is the value of x + 5. The variable xhas a value of 10 and so now becomes 15. As C# does not see both lines at the same time, it does not notice the circularity of the above definition.

Lab4

Program

using System;

namespace AccessModifiers
{
public class Program
{
int x = y + 10;
int y = x + 5;
public static void Main(string[] args)
{

}
}
}

Output

Compile time error:

A field initializer cannot reference the non-static field, method, or property ‘AccessModifiers.Program.y’
A field initializer cannot reference the non-static field, method, or property ‘AccessModifiers.Program.x’

The lab we did in Lab3 does not work for instance variables as the rules of an instance variable are quite different than that of static variables. The initializer of an instance variable has to be determined at the time of creation of the instance. The variable y does not have a value at this point in time. It can’t refer to variables of the same object at the time of creation. So we can refer to no instance members to initialize an instance member.

Readonly Fields

Readonly fields are one of the most interesting topics of OOP in C#.

Lab1

Program

using System;

namespace AccessModifiers
{
public class Program
{
public static readonly int x = 100;

public static void Main(string[] args)
{
Console.WriteLine(x);
Console.ReadKey();
}
}
}

Output

100
Wow, we get no error, but remember not to use a non static variable inside a static method, else we’ll get an error.

Lab2

Program

using System;

namespace AccessModifiers
{
public class Program
{
public static readonly int x = 100;

public static void Main(string[] args)
{
x = 200;
Console.WriteLine(x);
Console.ReadKey();
}
}
}

Output

Compile time error: A static readonly field cannot be assigned to
(except in a static constructor or a variable initializer).
We cannot change the value of a readonly field except in a constructor.
Point to remember: A static readonly field cannot be assigned to (except in a static constructor or a variable initializer).

Lab3

Program

using System;

namespace AccessModifiers
{
public class Program
{
public static readonly int x;

public static void Main(string[] args)
{
}
}
}

Here we find one difference between const and readonly, unlike constreadonly fields need not have to be initialized at the time of creation.

Lab4

Program

using System;

namespace AccessModifiers
{
public class Program
{
public static readonly int x;

static Program()
{
x = 100;
Console.WriteLine(Inside Constructor”);
}

public static void Main(string[] args)
{
Console.WriteLine(x);
Console.ReadKey();
}
}
}

Output

Inside Constructor
100
One more major difference between const and readonly is seen here. A static readonly variable can be initialized in the constructor as well, like we have seen in the above mentioned example.

Lab5

Program

using System;

namespace AccessModifiers
{
public class ClassA
{

}
public class Program
{

public readonly ClassA classA=new ClassA();
public static void Main(string[] args)
{
}
}
}

We have already seen this example in const section. The same code gave an error with const does not give an error with readonly fields. So we can say that readonly is a more generic const and it makes our programs more readable as we refer to a name and not a number. Is 10 more intuitive or priceofcookie easier to understand? The compiler would for efficiency convert all consts and readonly fields to the actual values.

Lab6

Program

using System;

namespace AccessModifiers
{
public class ClassA
{
public int readonly x= 100;
}
public class Program
{
public static void Main(string[] args)
{
}
}
}

Output

Compile time error:

Member modifier ‘readonly’ must precede the member type and name
Invalid token ‘=’ in class, struct, or interface member declaration

Wherever we need to place multiple modifiers, remind yourself that there are rules that decide the order of access modifiers, which comes first. Now here the readonly modifier precedes the data type int, we already discussed at the very start of the article. This is just a rule that must always be remembered.

Lab7

Program

using System;

namespace AccessModifiers
{
public class ClassA
{
public readonly int x= 100;

void Method1(ref int y)
{

}

void Method2()
{
Method1(ref x);
}
}
public class Program
{

public static void Main(string[] args)
{
}
}
}

Output

Compile time error:

A readonly field cannot be passed ref or out (except in a constructor)
A readonly field can’t be changed by anyone except a constructor.
The method Method1 expects a ref parameter which if we have forgotten allows you
to change the value of the original. Therefore C# does not permit a readonly
as a parameter to a method that accepts a ref or an out parameters.

Summary

Let’s recall all the points that we have to remember:
  1. The default access modifier is private for class members.
  2. A class marked as internal can have its access limited to the current assembly only.
  3. Namespaces as we see by default can have no accessibility specifiers at all. They are by default public and we cannot add any other access modifier including public again too.
  4. A class can only be public or internal. It cannot be marked as protected or private. The default isinternal for the class.
  5. Members of a class can be marked with all the access modifiers, and the default access modifier is private.
  6. Protected internal means that the derived class and the class within the same source code file can have access.
  7. Between public and internalpublic always allows greater access to its members.
  8. Base class always allows more accessibility than the derived class.
  9. The return values of a method must have greater accessibility than that of the method itself.
  10. A class marked sealed can’t act as a base class to any other class.
  11. Since we cannot derive from sealed classes, the code from the sealed classes cannot be overridden.
  12. We need to initialize the const variable at the time we create it. We are not allowed to initialize it later in our code or program.
  13. Like classes, const variables cannot be circular, i.e., they cannot depend on each other.
  14. const field of a reference type other than string can only be initialized with null.
  15. One can only initialize a const variable to a compile time value, i.e., a value available to the compiler while it is executing.
  16. A constant by default is static and we can’t use the instance reference, i.e., a name to reference a const. Aconst has to be static as no one will be allowed to make any changes to a const variable.
  17. const variable cannot be marked as static.
  18. A variable in C# can never have an uninitialized value.
  19. Static variables are always initialized when the class is loaded first. An int is given a default value of zero and a bool is given a default of False.
  20. An instance variable is always initialized at the time of creation of its instance.
  21. static readonly field cannot be assigned to (except in a static constructor or a variable initializer).

Conclusion

With this article, we completed almost all the scenarios of access modifiers. We did a lot of hands-on lab to clear our concepts. I hope my readers now know by heart about these basic concepts and will never forget them. In my upcoming article, i.e., the last article of this series, we’ll be discussing about Properties and Indexers in C#.
Keep coding and enjoy reading. 
Also do not forget to rate/comment/like my article if it helped you by any means, this helps me get motivated and encourages me to write more and more.

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 (Day 4): Polymorphism and Inheritance (All About Abstract Classes in C#)


1. Introduction

We learnt a lot about polymorphism and inheritance. In this article of the series “Diving in OOP”, we’ll discuss about the most hot and exciting topic of OOP in C#, i.e., Abstract Classes. The concept of Abstract classes is the same for any other language, but in C# we deal with it in a bit different way. Abstract classes play a different and very interesting role in polymorphism and inheritance. We’ll cover all the aspects of abstract classes with our hands-on lab and theory as an explanation to what output we get. We’ll also list down points to remember at the end of the article.

Pre-requisites

Wonder, we are dealing with the fourth part of our learning objective. Now my only expectation with my readers is to enjoy the series.

2. Roadmap

Let’s recall our road map:

3. Abstract Classes

Let’s get the definition from MSDN:

“The abstract keyword enables you to create classes and class members that are incomplete and must be implemented in a derived class. An abstract class cannot be instantiated. The purpose of an abstract class is to provide a common definition of a base class that multiple derived classes can share. For example, a class library may define an abstract class that is used as a parameter to many of its functions, and require programmers using that library to provide their own implementation of the class by creating a derived class.
Abstract classes may also define abstract methods. This is accomplished by adding the keyword abstract before the return type of the method.”

4. Abstract Classes in Action

Add a console application named “InheritanceAndPolymorphism” in your Visual Studio. You’ll get a class namedProgram.cs, just add one more class named ClassA.cs, note that the ClassA should be marked abstract, and the following code to ClassA.cs and Program.cs:
using System;

namespace InheritanceAndPolymorphism
{
public abstract class ClassA
{

}

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

Compile the code.

Output

Compile time error: Cannot create an instance of the abstract class or interface 'InheritanceAndPolymorphism.ClassA'
 
Point to remember: We cannot create an object of abstract class using new keyword.
Now we go into understanding the concept. No power can stop abstract keyword to be written before a class. It acts as a modifier to the class. We cannot create an object of abstract class using new keyword. Seems that the class is useless for us as we cannot use it for other practical purposes as we used to do.

5. Non Abstract Method Definition in Abstract Class

Let’s add some code to our abstract class:
    /// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {

}
}

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

We again see the error that we encountered earlier. Again, it reminds that we cannot use new if we have already used an abstract modifier.

6. Abstract Class Acting as a Base Class

Let’s add one more class now:
    /// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {

}
}

/// <summary>
/// Derived class.
/// Class derived from abstract class ClassA
/// </summary>
public class ClassB:ClassA
{

}

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

We get no error? A class can be derived from abstract class. Creating an object of ClassB does not gives us any error.
 
Point to remember: A class can be derived from an abstract class.
 
Point to remember: A class derived from an abstract class can create an object.

7. Non Abstract Method Declaration in Abstract Class

Another scenario:
    /// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {

}

public void YYY();
}

/// <summary>
/// Derived class.
/// Class derived from abstract class ClassA.
/// </summary>
public class ClassB:ClassA
{

}

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

We just declared a method named YYY() in our abstract class ClassA.
Compile the code, we get:

Output

Compile time error: 'InheritanceAndPolymorphism.ClassA.YYY()' 
must declare a body because it is not marked abstract, extern, or partial
 
InheritanceAndPolymorphism is the namespace I used for my console application so you can ignore that, no need to confuse with the logic.
In the above code, we just added a method declaration in the abstract class. An abstract method indicates that the actual definition or code of the method is created somewhere else. The method prototype declared in abstractclass must also be declared abstract as per the rules of C#.

8. Abstract Method Declaration in Abstract Class

Just make the method YYY() as abstract in ClassA:
    /// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {

}

abstract public void YYY();
}

/// <summary>
/// Derived class.
/// Class derived from abstract class ClassA.
/// </summary>
public class ClassB:ClassA
{

}

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

Output

Compiler error: 'InheritanceAndPolymorphism.ClassB' does not implement 
inherited abstract member 'InheritanceAndPolymorphism.ClassA.YYY()'
 
Point to remember: If we declare any method as abstract in our abstract class, then it’s the responsibility of the derived class to provide the body of that abstract method, unless a body is provided for that abstract method, we cannot create an object of that derived class.
In the above mentioned scenario, we declared method YYY() as abstract in ClassA. Since ClassB derives fromClassA, now it becomes the responsibility of ClassB to provide the body of that abstract method, else we cannot create an object of ClassB.

9. Abstract Method Implementation in Derived Class

Now provide a body of method YYY() in ClassB. Let’s see what happens:
    /// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {

}

abstract public void YYY();
}

/// <summary>
/// Derived class.
/// Class derived from abstract class ClassA.
/// </summary>
public class ClassB:ClassA
{
public void YYY()
{

}
}

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

Everything seems fine now, but no? Compile the code, what we get:

Output

Two compile time errors this time:
Compile time error: 'InheritanceAndPolymorphism.ClassB' does not implement 
inherited abstract member 'InheritanceAndPolymorphism.ClassA.YYY()'

Compile time warning: ‘InheritanceAndPolymorphism.ClassB.YYY()’ hides
inherited member ‘InheritanceAndPolymorphism.ClassA.YYY()’.

To make the current member override that implementation, add the override keyword. Otherwise add the newkeyword.
We have been continuously trying to compile our code, but no success till now. The compiler error indicates clearly that both of our base and derived class contains the same method named YYY().
If both our derived class and base class contain the method with the same name, always an error occurs. The only way to overcome this error is derived class explicitly add the modifier override to its method signature. We have already discussed such scenarios in our previous parts of the articles of Diving in OOP series.
Let’s add the override keyword before derived class method YYY().
/// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {

}

abstract public void YYY();
}

/// <summary>
/// Derived class.
/// Class derived from abstract class ClassA.
/// </summary>
public class ClassB:ClassA
{
public override void YYY()
{

}
}

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

We get no warning or error now?

10. Abstract Method Implementation in Derived Class with Different Return Type

Let’s just change the return type of the method YYY() in derived class:
  /// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {

}

abstract public void YYY();
}

/// <summary>
/// Derived class.
/// Class derived from abstract class ClassA.
/// </summary>
public class ClassB:ClassA
{
public override int YYY()
{

}
}

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

We changed return type of method YYY from void to int in derived class. Compile the code.

Output

Compile time error: 'InheritanceAndPolymorphism.ClassB.YYY()': return type must be 'void' 
to match overridden member 'InheritanceAndPolymorphism.ClassA.YYY()'
Therefore one more constraint.
 
Point to remember: When we override an abstract method from a derived class, we cannot change the parameters passed to it or the return type irrespective of the number of methods declared as abstract in abstractclass.
Let’s see the implementation of the second line mentioned in “point to remember”,
    /// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {

}

abstract public void YYY();
abstract public void YYY1();
abstract public void YYY2();
abstract public void YYY3();
}

/// <summary>
/// Derived class.
/// Class derived from abstract class ClassA.
/// </summary>
public class ClassB:ClassA
{
public override int YYY()
{

}
}

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

Compiler error:
'InheritanceAndPolymorphism.ClassB' does not implement 
inherited abstract member 'InheritanceAndPolymorphism.ClassA.YYY3()'

‘InheritanceAndPolymorphism.ClassB’ does not implement inherited
abstract member ‘InheritanceAndPolymorphism.ClassA.YYY2()’

‘InheritanceAndPolymorphism.ClassB’ does not implement inherited
abstract member ‘InheritanceAndPolymorphism.ClassA.YYY1()’

If we implement these three methods in derived class, we’ll get no error.
Point to remember: An abstract class means that the class is incomplete and cannot be directly used. Anabstract class can only be used as a base class for other classes to derive from.

11. Variable Initialization in Abstract Class

Therefore as seen earlier, we get an error if we use a new keyword on an abstract class. If we do not initialize a variable in an abstract class like we used a, it will automatically have a default value of 0 which is what the compiler kept warning us about. We can initialize int variable a of ClassA to any value we wish. The variables in abstractclass act similar to that in any other normal class.

12. Power of Abstract Class

Whenever a class remains incomplete, i.e., we do not have the code for some methods, we mark those methodsabstract and the class is marked abstract as well. And so, we can compile our class without any error or blocker. Any other class can then derive from our abstract class but they have to implement the abstract, i.e., our incomplete methods from abstract class.
Abstract therefore enables us to write code for a part of the class and allows the others (derived classes) to complete the rest of the code.

13. Abstract Method in Non Abstract Class

Let’s take another code block:
    /// <summary>
    /// Abstract class ClassA
    /// </summary>
    public class ClassA
    {
        public int a;
        public void XXX()
        {

}

abstract public void YYY();
}

/// <summary>
/// Derived class.
/// Class derived from abstract class ClassA.
/// </summary>
public class ClassB:ClassA
{
public override void YYY()
{

}
}

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

Compile the code.

Output

Compiler error: 'InheritanceAndPolymorphism.ClassA.YYY()' is abstract 
but it is contained in non-abstract class 'InheritanceAndPolymorphism.ClassA'
We just removed abstract keyword from class ClassA. The error clearly conveys a message that if a single method is marked abstract in a class, then the class will have to be abstract as well.
 
Point to remember: If a class has even a single abstract method, then the class has to be declared abstract as well.
 
Point to remember: An abstract method also cannot use the modifiers such as static or virtual.
We can only have the abstract method in an abstract class. Any class that derives from abstract class has to give implementation to its abstract method. By default, the modifier new gets added to the derived class method, that makes it a new/different method.

14. Abstract Base Method

    /// <summary>
    /// Abstract class ClassA
    /// </summary>
    public abstract class ClassA
    {
        public int a;
        public void XXX()
        {

}

abstract public void YYY();
}

/// <summary>
/// Derived class.
/// Class derived from abstract class ClassA.
/// </summary>
public class ClassB:ClassA
{
public override void YYY()
{
base.YYY();
}
}

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

Output

Compile time error : Cannot call an abstract base member: 
'InheritanceAndPolymorphism.ClassA.YYY()'
We cannot call the method YYY() from the base class ClassA as it does not carry any implementation/code along with it and has also been declared abstract. Common sense prevails? and C# off course does not allow us to call a method that does not contain code.

15. Abstract Class Acting as Derived as Well as Base Class

Let’s modify our code a bit, and prepare our class structure something as follows:
    /// <summary>
    /// Base class ClassA
    /// </summary>
    public class ClassA
    {
        public virtual void XXX()
        {
            Console.WriteLine("ClassA XXX");
        }
    }

/// <summary>
/// Derived abstract class.
/// Class derived from base class ClassA.
/// </summary>
public abstract class ClassB:ClassA
{
public new abstract void XXX();
}

public class ClassC:ClassB
{
public override void XXX()
{
System.Console.WriteLine(ClassC XXX”);
}
}

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

Compile the code, and run.

Output

ClassA XXX
ClassC XXX
We created a base class named ClassA that is not abstract and added a virtual method XXX to it. Since the method is non abstract but marked virtual so it has to be overridden in its deriving class. We added one more class named ClassB and marked that class abstract, note that this class is derived from ClassA. So this class has a choice to override the method marked as virtual in base class. But we’ll do something different and tricky,
We marked XXX method in this derived class as new abstract, and did not give anybody to this method. Now what? We will add one more class ClassC, that will derive from ClassBClassC has no choice but to override the methodXXX. Therefore we override the method XXX in ClassC.
In main method, we created two objects ClassA classA = new ClassC(); and ClassB classB = new ClassC();
First object looks like that of ClassC but refers to ClassA and second one again seems to be like ClassC but refers to ClassB.
In case of classA.XXX() will definitely first look into the class ClassA. Here, it finds the method XXX marked as virtual. These kind of scenarios we have already taken n number of times in our earlier articles where we discussed about run time polymorphism . C# will then crawl over to class ClassB. Here it gets shocked that the method XXX()is abstract, i.e., there is no code or implementation for method XXX() and also that it is a method marked as new, thus severing all links with the base class. And so flow halts and all and the method XXX() from ClassA gets executed.
In the case of b.XXX()(), since the method is new, the links to the base class gets broken, we are left with no choice but to invoke the method from ClassC as it says override.
We cannot replace the modifier new with the keyword override for the method XXX() in abstract class ClassB.
Let’s replace the override modifier in ClassC with “new” like:
 public class ClassC:ClassB
     {
        public new void XXX()
        {
            System.Console.WriteLine("ClassC XXX");
        }
     }

Output

Compile time error: 'InheritanceAndPolymorphism.ClassC' does not implement 
inherited abstract member 'InheritanceAndPolymorphism.ClassB.XXX()'
The error indicates that as there is no code for the method XXX. Remember the XXX() of class ClassA has nothing to do at all with that of ClassB and ClassC.
Also there is one more point to remember.
 
Point to remember: Virtual methods run slower that non virtual methods.

16. Can Abstract Class be Sealed?

Let’s take this final question into our consideration. Let’s test this too with an example.
    /// <summary>
    /// sealed abstract class ClassA
    /// </summary>
    public sealed abstract class ClassA
    {
        public abstract void XXX()
        {
            Console.WriteLine("ClassA XXX");
        }
    }

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

Compile the code.

Output

Compile time error: 'InheritanceAndPolymorphism.ClassA': 
an abstract class cannot be sealed or static
And so we get two points to remember.
 
Point to rememberAbstract class cannot be sealed class.
 
Point to rememberAbstract class cannot be a static class.

17. Points to Remember

Let’s sum up all the points to remember:
  1. We cannot create an object of abstract class using new keyword.
  2. A class can be derived from an abstract class.
  3. Class derived from an abstract class can create an object.
  4. If we declare any method as abstract in our abstract class, then it’s the responsibility of the derived class to provide the body of that abstract method, unless a body is provided for that abstract method, we cannot create an object of that derived class.
  5. When we override an abstract method from a derived class, we cannot change the parameters passed to it or the return type irrespective of the number of methods declared as abstract in abstract class.
  6. An abstract class means that the class is incomplete and cannot be directly used. An abstract class can only be used as a base class for other classes to derive from.
  7. If a class has even a single abstract method, then the class has to be declared abstract as well.
  8. An abstract method also cannot use the modifiers such as static or virtual.
  9. Virtual methods run slower that non virtual methods.
  10. Abstract class cannot be sealed class.
  11. Abstract class cannot be a static class.

18. Conclusion

With this article, we complete our understanding of inheritance and polymorphism. We have covered almost all the aspects of Polymorphism and Inheritance. Abstract classes are one of my favorites so I just wanted to take them separately. I hope my readers enjoyed this article too and learnt about abstract classes in C#.
In my upcoming articles of the series, we’ll be discussing about other OOP features in the C# way with full hands-on lab and lot of discussion.
Keep coding and enjoy reading. 
Also do not forget to rate/comment/like my article if it helped you by any means. This helps me to get motivated and encourages me to write more and more.

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 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.