Access Modifers in C#

Introduction

Navigating the coding terrain involves understanding the key players, and access modifiers take center stage. These language elements define how different parts of our code interact, dictating who can see and use what. Let's delve into this crucial aspect of coding, unraveling the roles of private, public, internal, protected, and the dynamic duo, protected internal.

Let's have a look at each with a simple and straight example.

1. Private

Embrace the power of "private" in your code!  By declaring a member as private in a class, you're setting clear boundaries. This encapsulation ensures that the member is accessible only within the defining type. Tight control for robust and secure code!

class Program
{
    class AccessMdf
    {
        private int num1;
    }
    static void Main(string[] args)
    {
        AccessMdf ob1 = new AccessMdf();
        //private member is not accessed
        ob1.num1 = 20;
        Console.ReadLine();
    }
}

2. Public

Go public for maximum reach!  When you declare a type or member as public, it becomes accessible from any code in any assembly. Embrace openness and collaboration in your codebase!

class Program
{
    class AccessMdf
    {
        public int num1;
    }
    static void Main(string[] args)
    {
        AccessMdf ob1 = new AccessMdf();
        //Direct access to public members
        ob1.num1 = 100;
        Console.ReadLine();
    }
}

3. Internal

Demystifying "internal" access! It grants access within the program that houses its declarations and extends to files within the same assembly. However, the magic stops at assembly boundaries, keeping your code interactions controlled and secure! 

namespace internalmdf {

    // Declare class Complex as internal
    internal class internalMod {

        int num1;
        int num2;

        public void send(int n1, int n2) {
            num1 = n1;
            num2 = n2;
        }

        public void display() {
            Console.WriteLine("Num1 = {0}", num1);
            Console.WriteLine("Num2 = {0}", num2);
        }
    }

    // Driver Class
    class Program {

        // Main Method
        static void Main(string[] args) {
            internalMod in = new internalMod();

            // Accessible in class Program
            in.dend(10, 20);
            in.display();
        }
    }
}

//Not accessible for the below class due to other namespace

namespace OtherNm {

    class NotInternal {

        // Will give an error during compilation
        internalMod in1 = new internalMod();
        in1.send(20, 30);
    }
}

4. Protected

Unlock the power of "protected" members!  By designating a member as protected, you grant exclusive access within the class and its derived classes. Shielding your code from external interference while fostering class hierarchy cohesion!

class Program
{
    class Base
    {
        protected int num1;
    }
    class Derived : Base
    {
        public int num2;
        static void Main(string[] args)
        {
            Base ob1 = new Base();
            Derived ob2 = new Derived();
            ob2.num1 = 20;
            // Access to protected member as it is inherited by the Derived class
            ob2.num2 = 90;
            Console.ReadLine();
        }
    }
}

5. Protected internal

Meet the powerhouse combo: "protected internal"!  This access modifier not only opens doors within the assembly (thanks to its internal charm) but also extends its reach through inheritance. A versatile choice for code that demands both internal collaboration and inheritance flexibility!

//file : xyz.cs
public class XYZ {
    protected internal int value;
}

class ABC {

    // Trying to access
    // value in another class
    public void checkAccess() {
        // Member value is Accessible
        XYZ obj1 = new XYZ();
        obj1.value = 12;
    }
}

// file PQRS.cs file
namespace PQRS {

    class DEF: XYZ {

        // Main Method
        public static void Main(String[] args) {
            // Accessing value in another assembly
            DEF obj3 = new DEF();

            // Member value is Accessible
            obj3.value = 9;
            Console.WriteLine("Value = " + obj3.value);
        }
    }
}

Conclusion

Access modifiers guide how code interacts. From keeping things private to sharing openly, each has a role. "Protected internal" is like teamwork, allowing collaboration and flexibility.