Access Modifier In C# With Example

Introduction

Access modifiers are keywords used to specify the declared accessibility of a member or a type. These define the permission level to type members ( Methods, Properties, Events, Variables).

Background

All type and type members have an accessibility level which controls whether they can be used by the code in the same assembly in which the type declared or the code in the other assembly.

Points of Interest

  • Access modifiers are not allowed on namespaces. Namespaces have no access restrictions.
  • Top-Level types, which are not nested into other types, can only have internal or public accessibility. The default accessibility for these types is internal.
  • The accessibility of a nested type depends on its accessibility domain, which is determined by both the declared accessibility of the member and the accessibility domain of the immediately containing type.
  • Private,Protected and Protected Internal class we can't declare explicityly within namespace.
  • Struct members cannot be protected because the struct cannot be inherited.
  • The drived class can't have higher accessibility than its base class, i.e. you can't have a public class that drived from a internal class.
  • The accessibility of a member can never be higher than the accessibility of its containing type.
  • Interface can only be public or internal. And default to internal.
  • Enum are default to public so not accept any modifer.
  • Delegates are default to internal.

Description

Given below are the major access modifiers used with type or type members.

  • Public
  • Protected
  • Internal
  • Protected Internal
  • Private

Public

Using Public, access is not restricted; it means type or type members are accessible by the code in the same or other assembly that referenced it.

public class SampleClass1
{
    // Public variable
    public static int myPublicInt;
}

class Program
{
    static void Main(string[] args)
    {
        // Access to SampleClass1 fields
        SampleClass1.myPublicInt = 1; // Access is unlimited

        Console.WriteLine("Press any key to exit!");
        Console.ReadLine();
    }
}

Protected

Using Protected, access is limited to the class which declares that member and the immediate class which inherits that class. A protected member of a base class is accessible in a drived classs only if the access takes place through the derived class type.

Example

class ProtectedSample
{
    protected string Name = string.Empty;

    protected void Display()
    {
        Console.WriteLine("Name: " + Name);
    }
}

class Drived : ProtectedSample
{
    Drived()
    {
        this.Name = "John"; // Accessible
    }

    // Method will call ProtectedSample class Display method
    public void DisplayName()
    {
        this.Display();
    }
}

class Other
{
    Other()
    {
        (new ProtectedSample()).Name = "Mike"; // Error: Inaccessible due to its protection level
    }
}

Example 2

class ProtectedSample2
{
    protected string Name = string.Empty;

    static void Initialize(ProtectedSample2 objA, Drive objDrive)
    {
        objA.Name = "Mike";
        objDrive.Name = "Clark";
    }
}

class Drive : ProtectedSample2
{
    static void Initialize(ProtectedSample2 objA, Drive objDrive)
    {
        objA.Name = "Mike"; // Error: Cannot access protected member via a qualifier of type
                            // 'ProtectedSample2', the qualifier must be of type 'Drive'
        objDrive.Name = "John";
    }
}

Internal

Using Internal, access is limited to the current assembly not by other assembly. A common use of internal access is in component-based development because it enables a group of components to cooperate in a private manner without being exposed to the rest of the application code.

namespace Cons.Accessibility
{
    internal class InternalSample
    {
        public void Display()
        {
            Console.WriteLine("In InternalSample.Display");
        }
    }
}

namespace Cons.Other
{
    class Test
    {
        Cons.Accessibility.InternalSample obj = new Cons.Accessibility.InternalSample();

        public void Display()
        {
            obj.Display();  // Valid
        }
    }
}

// In different Assembly
using Cons.Accessibility;

namespace TestingApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            InternalSample obj = new Cons.Accessibility.InternalSample();  // Error: Inaccessible due
                                                                           // to protection level
        }
    }
}

Protected Internal

Using Protected Internal, accessibility is limited to the code in assembly in which it is declared, or from within a drive class in another assembly. Access from another assembly must take place within a class declaration that derives from the class in which the protected internal element is declared, and it must take place through an instance of the derived class type.

namespace Cons.Accessibility
{
    public class ProtectedInternalSample
    {
        protected internal string Name = string.Empty;

        protected void Display()
        {
            Console.WriteLine("Name: " + this.Name); // Valid
        }
    }

    public class PIDrived : ProtectedInternalSample
    {
        PIDrived()
        {
            this.Name = "John"; // Valid
        }
    }
}

// Other Namespace but same assembly
namespace Others
{
    class Other
    {
        Other()
        {
            Cons.Accessibility.ProtectedInternalSample obj = new Cons.Accessibility.ProtectedInternalSample();
            obj.Name = "Mike";
        }
    }
}

// Diff assembly
using Cons.Accessibility;

namespace TestingApplication
{
    class Program : ProtectedInternalSample
    {
        public void UpdateName()
        {
            Name = "Clark"; // Valid
        }
    }
}

In the above example, if we remove Protected keyword from the Name variable, then it will not be accessible in diff assembly.

Private

Using Private, accessibility is limited to the code that are only in containted type.

class PrivateSample
{
    private string Name = string.Empty;

    public void Initialize()
    {
        this.Name = "John";
    }
}

class POther
{
    public void Initialize()
    {
        PrivateSample obj = new PrivateSample();
        obj.Name = "Mike";    // Error: Inaccessible due to protection level
        obj.Initialize();     // Valid
    }
}

Hope this will add some knowledge to your knowledge base.

Next Recommended Reading Access Modifiers In C#