C#

Understanding the Concept of Nested Classes in C#

Programmingempire

In this post on Understanding the Concept of Nested Classes in C#, I will explain the Nested Types using several examples. Basically, a nested type encloses the definition of another type.

Important Points to Remember about Nested Types

  1. The nested class is not accessible outside the containing class since it is a member of the containing class. Hence, it is considered as the private member of the outer class.
  2. However, the nested class can access the members of the containing class.
  3. Also, the nested type can also have access to the containing type, if we pass its object as a parameter to the constructor.
  4. Since it is a member of the containing class, all of the access modifiers are applicable to it. Therefore, we can use private, protectedpublicinternalprivate protected, and protected internal access modifiers with the nested class.
  5. In contrast, a nested struct can have public, internal, and private access modifiers only.
  6. Moreover, if the outer class is inherited from some other class, then the nested class also has access to all of the inherited members.
  7. A sealed class can also have nested types. However, in such cases, the nested types can not use protectedprotected internal, or private protected access modifiers.

Few examples of using Nested Classes are provided next that help you in Understanding the Concept of Nested Classes in C#.

In the example given below, there are two containing classes – Outer1 and Outer2, while Outer2 is the subclass of Outer1. Now that, Outer1 contains four inner classes namely inner1, inner2, inner3, and inner 4 with access modifiers public, private, protected, and internal respectively. Additionally, Outer2 also has an inner class of its own called inner11 and inherited inner classes inner3 and inner1. As evident from the following code, the Main() method creates several objects of the containing and nested classes.

using System;
namespace NestedTypesDemo
{
    class Outer1
    {
        public Outer1()
        {
            Console.WriteLine("Inside Constructor of Outer1");
        }
        public void f1()
        {
            Console.WriteLine("Inside Outer1.f1()");
        }
        public class inner1
        {
            Outer1 ob=new Outer1();
            public inner1()
            {
                Console.WriteLine("Inside Default Constructor of Inner1");
            }
            public inner1(Outer1 ob)
            {
                Console.WriteLine("Inside Parameterized Constructor of Inner1");
                this.ob = ob;
            }
            public void f1()
            {
                Console.WriteLine("Inside inner1.f1()");
                ob.f1();
                inner2 ob2 = new inner2();
                Console.WriteLine(ob2.f2(2, 5));
                inner4 ob3 = new inner4();
                Console.WriteLine(ob3.f3(2, 5));
                inner3 ob4 = new inner3();
                Console.WriteLine(ob4.f4(2, 5));
            }
        }
        private class inner2
        {
            public int f2(int a, int b)
            {
                Console.WriteLine("Inside inner2.f2()");
                return a + b;
            }
        }
        protected class inner3
        {
            public int f4(int a, int b)
            {
                Console.WriteLine("Inside inner3.f4()");
                return a * a + b * b;
            }
        }
        class inner4
        {
            public int f3(int a, int b)
            {
                Console.WriteLine("Inside inner4.f3()");
                return a * b;
            }
        }
    }
    class Outer2: Outer1
    {
        public class inner11
        {
            inner3 x = new inner3();
            inner1 y = new inner1();
            public inner11()
            {
                Console.WriteLine("Inside Constructor of inner11");
                Console.WriteLine(x.f4(4, 6));
                y.f1();
            }
        }
        public Outer2()
        {
            Console.WriteLine("Inside Constructor of Outer2");
            inner11 z = new inner11();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Outer1 ob = new Outer1();
            Console.WriteLine();
            Outer1.inner1 ob1 = new Outer1.inner1();
            Console.WriteLine();
            ob.f1();
            Console.WriteLine();
            ob1.f1();
            Console.WriteLine();

            Outer2 ob2 = new Outer2();
            Console.WriteLine();
            Outer2.inner11 ob3 = new Outer2.inner11();
            Console.WriteLine();
            Outer2.inner1 ob4 = new Outer1.inner1();
            Console.WriteLine();

            Outer1.inner1 ob5 = new Outer1.inner1(ob);
            Console.WriteLine();
            ob5.f1();
            Console.WriteLine();
            ob5.f1();
            Console.WriteLine();
        }
    }
}

Output

  1. We create the object of Outer1 and Outer1.inner1 since it is public and therefore accessible in the Main() method.
  2. Further, we call the methods f1() and f2() of these classes.
Understanding the Concept of Nested Classes in C#
Nested Classes in C#

This example also demonstrates the accessibility of inner classes in the case of inheritance. As discussed earlier, both inner11 and inner1 are accessible with Outer2. Also, note that we can pass the object of Outer1 as a parameter in the constructor of inner1.

Inheritance in Nested Classes
Inheritance in Nested Classes

Summary

This article on Understanding the Concept of Nested Classes in C#, demonstrates the concept of nested classes, their accessibility, and inheritance using examples in C#. In fact, the example given here describes how we can use nested classes in several possible ways.


programmingempire

You may also like...