What are Access Specifiers or Access Modifiers in C#?

In encapsulation, before creating any types you must always consider scope of the type or visibility of the type.  C# provides various number of keywords to decide the scope, those are private(default one), public, internal, protected and protected internal. If you create any type without these keywords, by default it will take as private.

Here we will discuss about each access specifier with an example. I created Class1.cs class which has several methods with the different access modifiers as shown below.

namespace AccessSpecifiers
{
    public class Class1
    {
        public void display1()
        {
            Console.WriteLine("public Access Specifier");
        }
        private void display2()
        {
            Console.WriteLine("Private Access Specifier");
        }
        internal void display3()
        {
            Console.WriteLine("internal Access Specifier");
        }
        protected void display4()
        {
            Console.WriteLine("protected Access Specifier");
        }
        protected internal void display5()
        {
            Console.WriteLine("protected internal Access Specifier");
        }
    }
}

private Access Specifier or Modifier:

The scope of the private members is limited with in the Class or Structure in which they are defined. They are not accessible outside the Class or Structure.

In the attached example, we have display2() method which is defined as private in Access Specifiers project, Class1.cs class.

We tried to access this method in the Class2.cs class and Class3.cs class (which is derived from Class1.cs class). But it produces the error as AccessSpecifiers.Class1.display2() is inaccessible due to its protection level.

class Class2
{
    void display()
    {
        Class1 obj = new Class1();
        obj.display2(); // Error, because display2() is private
    }
}

class Class3 : Class1
{
    void display()
    {
        display2(); // Error, because display2() is private
    }
}

public Access Specifier or Modifier:

Public members have no access restriction. You can access public members by creating object, in derived class and with in the assembly and in other assemblies also.

We have display1() method which is defined as public in AccessSpecifiers project, Class1.cs class.  We can access this method in Class2.cs class by creating object, in Class3.cs class which is derived from Class1.cs class and also in other assembly AccessSpecifiersTest also.

namespace AccessSpecifiers
{
    class Class2
    {
        void display()
        {
            Class1 obj = new Class1();
            obj.display1(); // No Error, because display1() public
        }
    }
}
namespace AccessSpecifiers
{
    class Class3 : Class1
    {
        void display()
        {
            display1(); // No Error, because display1() public
        }
    }
}

In other assembly AccessSpecifiersTest,

namespace AccessSpecifiersTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // try to access AccessSpecifier Assembly methods
            AccessSpecifiers.Class1 obj = new AccessSpecifiers.Class1();
            obj.display1(); // public method, No Error
        }
    }
}

protected Access Specifier or Modifier:

You cannot access protected members directly i.e., you cannot access protected members by creating object. You can access protected memebers in derived class only.

We have display4() method which is defined as protected in AccessSpecifiers project, Class1.cs class.  We can access this method in Class3.cs class which is derived from Class1.cs class and elsewhere you cannot access this method.

namespace AccessSpecifiers
{
    class Class2
    {
        void display()
        {
            Class1 obj = new Class1();
            obj.display4(); // Error, because display4() is protected
        }
    }
}
namespace AccessSpecifiers
{
    class Class3 : Class1
    {
        void display()
        {
            display4(); // No Error, because display4() is protected
        }
    }
}
namespace AccessSpecifiersTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // try to access AccessSpecifier Assembly methods
            AccessSpecifiers.Class1 obj = new AccessSpecifiers.Class1();
            obj.display4();  // Error, because display4() is protected
        }
    }
}

internal Access Specifier or Modifier:

Internal members are accessible with in the assembly only. You cannot access internal members outside of the assembly.

We have display3() method which is defined as internal in AccessSpecifiers project, Class1.cs class.  We can access this method in Class2.cs class by creating object, in Class3.cs class which is derived from Class1.cs class. Because Class2.cs and Class3.cs classes are in the same assembly AccessSpecifiers. You cannot access display3() method other assembly AccessSpecifiersTest, it produces compile time error.

namespace AccessSpecifiers
{
    class Class2
    {
        void display()
        {
            Class1 obj = new Class1();
            obj.display3(); // No Error, because display3() is internal
        }
    }
}
namespace AccessSpecifiers
{
    class Class3 : Class1
    {
        void display()
        {
            display3(); // No Error, because display3() is internal
        }
    }
}
namespace AccessSpecifiersTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // try to access AccessSpecifier Assembly methods
            AccessSpecifiers.Class1 obj = new AccessSpecifiers.Class1();
            obj.display3(); // Error, because display3() is internal
        }
    }
}

protected internal Access Specifier or Modifier:

Protected internal scope is addition of protected and internal scope. That means protected internal members are accessible in the derived class as well as with in the assembly.

We have display5() method which is defined as protected internal in AccessSpecifiers project, Class1.cs class.  We can access this method in Class2.cs class by creating object, in Class3.cs class which is derived from Class1.cs class, but we cannot access in other assembly AccessSpecifiersTest.

namespace AccessSpecifiers
{
    class Class2
    {
        void display()
        {
            Class1 obj = new Class1();
            obj.display5(); // No Error, because display5() is protected internal
        }
    }
}
namespace AccessSpecifiers
{
    class Class3 : Class1
    {
        void display()
        {
            display5(); // No Error, because display5() is protected internal
        }
    }
}
namespace AccessSpecifiersTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // try to access AccessSpecifier Assembly methods
            AccessSpecifiers.Class1 obj = new AccessSpecifiers.Class1();
            obj.display5(); // Error, because display5() is protected internal
        }
    }
}