Wednesday, May 26, 2021

C# Constructor Chaining

What is Constructor Chaining?
When a constructor calls another constructor, it is called constructor chaining. There are two possible scenario of constructor chaining.
  1. When a constructor invokes another constructor inside its own class.
  2. When a constructor invokes another constructor inside another class.
Let's first look at the first case. Suppose that in a class named Chain there are two parameterized constructors. We will invoke the default parameter-less constructor and the parameterized constructor will be invoked. Which parameterized constructor will be called is decided by the nature of parameters passed to the this operator. The this() invokes the constructor of the class in which it is called. This is illustrated in the following examples.

EXAMPLE 1

using System;
namespace ConsoleCChain
{
    class Chain
    {
        int x;
        public Chain():this(2,4) // parameter-less constructor calls two-parameter constructor
        {
            Console.WriteLine("Inside this");
        }
        public Chain(int number)
        {
            this.x = number;
            Console.WriteLine("Single Parameter");
        }
        public Chain(int number1, int number2)
        {
            this.x = number1 + number2;
            Console.WriteLine("Two Parameters");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Chain c = new Chain();// default constructor

            Console.ReadKey();
        }
    }
}

NOTE: In the Main method, the default constructor is called which in turn calls the two-parameter constructor. So, "Two Parameters" is printed. Then control returns to the caller constructor and hence default constructor is called. So, "Inside this" is printed thereafter.
OUTPUT
Two Parameters
Inside this

EXAMPLE 2

    using System;
    namespace ConsoleCChain
    {
        class Chain
        {
            int x;
            public Chain()
            {
                Console.WriteLine("Inside parameterless");
            }
//Chain(int number) constructor will invoke two-parameter constructor
//then it will invoke itself
            public Chain(int number) : this(2, 4) // this will call two-parameters constructor
            {
                this.x = number;
                Console.WriteLine("Single Parameter");
            }
            public Chain(int number1, int number2)
            {
                this.x = number1 + number2;
                Console.WriteLine("Two Parameters");
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Chain c = new Chain(3);// one-parameter constructor

                Console.ReadKey();
            }
        }
    }
NOTE: In the Main method, the one-parameter constructor is called which in turn calls the two-parameter constructor. So the body of the  two-parameter constructor is executed and then one-parameter constructor is called.
OUTPUT
Two Parameters
Single Parameter

Let's now look at the second case. For this case, we should have the knowledge of Inheritance beforehand. We will consider base class and derived class. We will understand how the base class constructor is invoked by the derived class constructor and then we will understand how programmer can call a constructors in chain as per the need. 

Example1

 using System;
    namespace ConsoleCChain
    {
        class Chain
        {
            int x;
            public Chain()
            {
                Console.WriteLine("Inside parameterless");
            }
            public Chain(int number)
            {
                this.x = number;
                Console.WriteLine("Single Parameter");
            }
            public Chain(int number1, int number2)
            {
                this.x = number1 + number2;
                Console.WriteLine("Two Parameters");
            }
        }
        class Derived : Chain
        {
        // no member 
        }
        class Program
        {
            static void Main(string[] args)
            {
            Derived d = new Derived();//constructor invoked

                Console.ReadKey();
            }
        }
    }
NOTE: When Derived class constructor is called, it calls its parent class, Chain default constructor. Then it calls its own default parameter-less constructor, which cannot given in the code. The output reflects this fact.
OUTPUT
Inside parameterless
Example2

Now, we add a constructor in the Derived class and see the output.
    using System;
    namespace ConsoleCChain
    {
        class Chain
        {
            int x;
            public Chain()
            {
                Console.WriteLine("Inside parameterless");
            }
            public Chain(int number)
            {
                this.x = number;
                Console.WriteLine("Single Parameter");
            }
            public Chain(int number1, int number2)
            {
                this.x = number1 + number2;
                Console.WriteLine("Two Parameters");
            }
        }
        class Derived : Chain
        {
        public Derived()
        {
            Console.WriteLine("Parameterless Derived Const.");
        }
        }
        class Program
        {
            static void Main(string[] args)
            {
            Derived d = new Derived();

                Console.ReadKey();
            }
        }
    }
NOTE: When Derived class constructor is called, it calls its parent class Chain parameter-less constructor. Then it calls its own parameter-less parameter-less constructor. The output reflects this fact.
OUTPUT
Inside parameterless
Parameterless Derived Const.

Now we can understand how a constructor of derived class invokes constructor of base class. As this keyword was used in the first case, the base keyword is used to in the second case.

The base keyword is used to access members of the base class from within a derived class:
  1. Call a method on the base class that has been overridden by another method.
  2. Specify which base-class constructor should be called when creating instances of the derived class.
  3. A base class access is permitted only in a constructor, an instance method, or an instance property accessor.
It is an error to use the base keyword from within a static method.

The base class that is accessed is the base class specified in the class declaration. For example, if you specify class ClassB : ClassA, the members of ClassA are accessed from ClassB, regardless of the base class of ClassA.

The following example illustrates how base keyword works.
Example3

using System;
namespace ConsoleBase
{
    public class Parent
    {
        int number;

        public Parent()
        {
            Console.WriteLine("inside Parent: "+number);
        }

        public Parent(int i)
        {
            number = i;
            Console.WriteLine("inside Single Parameter Parent: "+number);
        }
    }
//Child class inherits the Parent class
    public class Child : Parent
    {
        // This constructor will call base class parameter-less constructor
        public Child() : base()
        {
        }

        // This constructor will call base class one-parameter constructor
        public Child(int i) : base(i)
        {
        }

        static void Main()
        {
            //Child class constructor called which calls base class parameterless constructor
            new Child();
            //Child class constructor called which calls base class one-parameter constructor
            new Child(1);
            Console.ReadKey();
        }
    }
}
OUTPUT
inside Parent: 0
inside Single Parameter Parent: 1
The following example illustrates how base keyword works.
Example4

using System;
namespace ConsoleBase
{
    public class Parent
    {
        int number;

        public Parent()
        {
            Console.WriteLine("inside Parent: "+number);
        }

        public Parent(int i)
        {
            number = i;
            Console.WriteLine("inside Single Parameter Parent: "+number);
        }
    }

    public class Child : Parent
    {
        // This constructor will call base class parameter-less constructor
        public Child() 
        {
        }

        // This parameterized constructor will call base class parameter-less  constructor
        public Child(int i) : base()
        {
        }

        static void Main()
        {
            //Child class constructor called which calls base class parameterless constructor
            new Child();
            //Child class constructor called which calls base class one-parameter constructor
            new Child(1);
            Console.ReadKey();
        }
    }    
}
OUTPUT
inside Parent: 0
inside Parent: 0

The following example illustrates how base keyword will not work.
Example5

using System;
namespace ConsoleBase
{
    public class Parent
    {
        int number;

        public Parent()
        {
            Console.WriteLine("inside Parent: "+number);
        }

        public Parent(int i)
        {
            number = i;
            Console.WriteLine("inside Single Parameter Parent: "+number);
        }
    }

    public class Child : Parent
    {
        // This constructor will throw error
        public Child() : base(i)
        {
        }

        // This constructor will call base class one-parameter constructor
        public Child(int i) : base(i)
        {
        }

        static void Main()
        {
            //Child class constructor called which calls base class  one-parameter constructor
            new Child();
            //Child class constructor called which calls base class one-parameter constructor
            new Child(1);
            Console.ReadKey();
        }
    }
}
The snapshot of code is below.

Example6

using System;
namespace ConsoleBase
{
    public class Parent
    {
        int number;

        public Parent()
        {
            Console.WriteLine("inside Parent: "+number);
        }

        public Parent(int i)
        {
            number = i;
            Console.WriteLine("inside Single Parameter Parent: "+number);
        }
    }

    public class Child : Parent
    {
        // This constructor will not throw error
        public Child() : base(7)
        {
        }

        // This constructor will call base class one-parameter constructor
        public Child(int i) : base(i)
        {
        }

        static void Main()
        {
            //Child class constructor called which calls base class  one-parameter constructor
            new Child();
            //Child class constructor called which calls base class one-parameter constructor
            new Child(1);
            Console.ReadKey();
        }
    }
}
OUTPUT
inside Single Parameter Parent: 7
inside Single Parameter Parent: 1


No comments:

Post a Comment

Hot Topics