Access Modifiers


Access modifiers in C# define the visibility and accessibility of classes, methods, and variables within a program. They help in encapsulation, ensuring that code components are properly restricted or exposed based on design requirements.

Why Use Access Modifiers?

Public


The public access modifier allows members to be accessible from anywhere within the program, including different classes and assemblies.

Key Characteristics:

Example:

public class Car
{
    public string Model;  // Public field accessible from anywhere

    public void Drive()   // Public method accessible from anywhere
    {
        Console.WriteLine("Driving...");
    }
}

Car myCar = new Car();
myCar.Model = "Toyota";  // Accessible from outside the Car class
myCar.Drive();           // Accessible from outside the Car class

Explanation:

Metaphor:
It's like a public park where everyone can enter and enjoy the facilities without any restrictions.

Common Use Cases:

Private


The private access modifier restricts access to members only within the same class, making them inaccessible from outside the class.

Key Characteristics:

Example:

public class BankAccount
{
    private decimal balance;  // Private field, accessible only within the class

    public void Deposit(decimal amount)
    {
        balance += amount;  // Accessible inside the class
    }

    public decimal GetBalance()
    {
        return balance;  // Exposing balance through a public method
    }
}

BankAccount account = new BankAccount();
account.Deposit(500);
// account.balance = 1000;  // Error: balance is private and cannot be accessed directly
Console.WriteLine(account.GetBalance());  // Accessing balance through a public method

Explanation:

Metaphor:
It's like a personal safe in your home—only you can access its contents, and others must go through you to retrieve anything.

Common Use Cases:

Protected


The protected access modifier allows members to be accessible within the same class and in derived (child) classes, but not from outside those classes.

Key Characteristics:

Example:

public class Animal
{
    protected string Species;  // Protected field accessible in derived classes (Animal -> ...)

    protected void SetSpecies(string species)
    {
        Species = species;  // Accessible within the base class
    }
}

public class Dog : Animal
{
    public void Identify()
    {
        SetSpecies("Canine");  // Accessible from the derived class
        Console.WriteLine($"This animal is a {Species}");
    }
}

Dog myDog = new Dog();
myDog.Identify();
// myDog.SetSpecies("Canine");  // Error: protected method cannot be accessed directly

Explanation:

Metaphor:
It's like family secrets—they are known within the family (class and subclasses) but hidden from outsiders.

Common Use Cases:

The difference between private and protected

The private access modifier restricts access to members within the same class, while the protected access modifier allows access within the same class and its derived classes.

public class Parent
{
    private int privateField;
    protected int protectedField;

    public void AccessFields()
    {
        privateField = 10;    // Accessible within the same class
        protectedField = 20;  // Accessible within the same class
    }
}

public class Child : Parent
{
    public void AccessFields()
    {
        // privateField = 10;    // Error: private field is not accessible in derived class
        protectedField = 20;  // Accessible in derived class
    }
}

Parent child = new Child();
// child.privateField = 10;    // Error: private field is not accessible in derived class
// child.protectedField = 20;  // Error: protected field is not accessible outside the class

Internal


The internal access modifier allows members to be accessible only within the same assembly, meaning they can be accessed by any code within the same project but not from another assembly.
TODO: Add a note about assembly
So, basically, assembly is a .dll or .exe file. We got it from the compilation of the code inside the certain project.

Key Characteristics:

Example.

Project A (Assembly 1):

internal class Logger
{
    internal void Log(string message)
    {
        Console.WriteLine($"Log: {message}");
    }
}

// Accessible within the same assembly
Logger logger = new Logger();
logger.Log("Logging internal data.");

Project B (Assembly 2):

// Error: Logger is not accessible from a different assembly
Logger logger = new Logger();
logger.Log("Logging internal data.");

Explanation:

Metaphor:
It's like company documents — accessible to all employees within the organization, but hidden from outsiders.

Common Use Cases:

Protected Internal


The protected internal access modifier allows members to be accessible within the same assembly and to derived (child) classes outside the assembly. This means the member can be accessed by any code within the same project, and also by subclasses in different assemblies.

Key Characteristics:

Example.

Project A (Assembly 1):

public class BaseClass
{
    protected internal void ShowMessage()
    {
        Console.WriteLine("Protected Internal Access");
    }
}

public class DerivedClass : BaseClass
{
    public void Display()
    {
        ShowMessage();  // Accessible in derived class within the same assembly
    }
}

// Accessible within the same assembly
BaseClass obj = new BaseClass();
obj.ShowMessage();  // Allowed within the same assembly

Project B (Assembly 2):

public class AnotherDerivedClass : BaseClass
{
    public void Test()
    {
        ShowMessage();  // Accessible because of inheritance
    }
}

// BaseClass obj = new BaseClass();
obj.ShowMessage();  // Error: Cannot access without inheritance

Explanation:

Metaphor:
It's like family privileges within an organization— family members can access certain resources outside of the company, but outsiders can't access them unless they are part of the family.

Common Use Cases:

Private Protected


The private protected access modifier allows members to be accessible within the same assembly but ONLY by derived (child) classes, restricting access even further compared to protected internal.

Key Characteristics:

Example.

Project A (Assembly 1):

public class BaseClass
{
    private protected void Display()
    {
        Console.WriteLine("Private Protected Access");
    }
}

public class DerivedClass : BaseClass
{
    public void Show()
    {
        Display();  // Accessible in derived class within the same assembly
    }
}

BaseClass obj = new BaseClass();
obj.Display();  // Error: Cannot access from outside the class hierarchy

Project B (Assembly 2):

public class AnotherDerivedClass : BaseClass
{
    public void Test()
    {
        Display();  // Error: Cannot access from a derived class in another assembly
    }
}

Explanation:

Metaphor:
It's like family secrets shared only within the household, accessible to close family members but not to extended family or outsiders.

Common Use Cases:

Sealed Keyword

The sealed keyword is used to prevent a class from being inherited by other classes. When a class is marked as sealed, it cannot be used as a base class for other classes.

Example:

public sealed class FinalClass
{
    public void Display()
    {
        Console.WriteLine("This is a sealed class");
    }
}

// Error: Cannot inherit from a sealed class
public class DerivedClass : FinalClass
{
    // Code here
}