C#  

Access Modifiers in C#

When we build software using C#, it is important to control how parts of our code can be accessed by others. This is where access modifiers come into play. Access modifiers help us define the visibility or scope of classes, methods, properties, and other members. It's like deciding which doors to lock, which ones to open, and who can enter the rooms in our software world.

Why Do We Need Access Modifiers?

Imagine we are building a bakery management system. Some information, like recipes, can be shared, but secret recipes should be protected. Similarly, some methods are for internal use only, while others should be available to the entire application.

Access modifiers give us the power to hide sensitive information and expose only what's necessary, making the code secure, organized, and easy to maintain.

What are Access Modifiers?

Access modifiers define the visibility of classes and their members in C#. They help us decide which parts of our code can be accessed by others and which should be kept private. It’s like controlling access to a kitchen; some areas are open to customers, some to staff only, and some are locked.

Types of Access Modifiers in C#

Access modifiers control how different parts of a program can interact with each other. By using them wisely, we can build secure, maintainable, and reusable applications.

access-modifiers

1. public: Open to Everyone

The public access modifier allows any part of the program or even other assemblies to access the class, method, or member without restriction. Use public when a feature or member is meant to be widely accessible, such as APIs, shared services, or data meant for interaction.

It’s like the bakery’s front door open for customers, suppliers, and delivery staff alike. Like, an online food delivery app where the restaurant name and menu must be accessible to all users.

Syntax

public class Bakery
{
    public string Name = "Sweet Treats";

    public void DisplayName()
    {
        Console.WriteLine("Welcome to " + Name);
    }
}

Use Case

  • For methods that form the interface to external components.

  • For properties that other parts of the system should freely access.

2. private: Lock It Down

The private access modifier restricts access so that only the same class can access the member or method. Even derived classes can’t access it. Use private when we want to hide implementation details or sensitive data that must not be altered externally.

The secret recipe is locked inside a safe, and only the head chef knows how to access it. In the real world, A payment gateway system where encryption keys or credentials must remain hidden.

Syntax

public class Bakery
{
    private string secretRecipe = "Chocolate Lava Cake";

    private void ShowSecret()
    {
        Console.WriteLine("The secret recipe is " + secretRecipe);
    }
}

Use Case

  • For configuration details, passwords, or internal calculations.

  • To prevent external code from accidentally changing the state of an object.

3. protected: Trusted Inheritance

The protected access modifier allows the member to be accessed within the class and by derived classes, but not by unrelated external classes. Use protected to expose functionality only to derived classes while keeping it hidden from outside users. In the Real world, A base class for employees where the salary structure is accessible to payroll-related derived classes but hidden from others.

The bakery’s special kitchen is only accessible to the head chef and trusted assistants.

Syntax

public class Bakery
{
    protected string kitchenSecret = "Special oven temperature";
}

public class AdvancedBakery : Bakery
{
    public void RevealSecret()
    {
        Console.WriteLine("The kitchen secret is " + kitchenSecret);
    }
}

Use Case

  • For methods or properties that subclasses need but should not be public.

  • Supports inheritance without exposing internals.

4. internal: Within the Same Assembly

The default access modifier is internal. The internal access modifier allows access only within the same assembly (project). Other assemblies cannot access it. Use internal when functionality is meant to be shared across classes within the same project but not exposed externally. In real world, An internal reporting service used only within an organization’s backend infrastructure.

A staff-only area inside the bakery where employees collaborate, but customers cannot enter.

Syntax

internal class BakeryHelper
{
    public void Assist()
    {
        Console.WriteLine("Helping in the bakery!");
    }
}

Use Case

  • For utility classes, helpers, or services meant to assist internal workflows.

  • Helps in modular development without leaking functionality.

5. protected internal: Hybrid Access

protected internal allows access to members within the same assembly or by derived classes from other assemblies. Use it when access needs to be available either for trusted inheritance or within the same project. In a real case, A framework’s base service class that can be extended by partner integrations.

Trusted helpers in the kitchen are accessible both by employees inside the bakery and chefs from partner locations.

Syntax

protected internal class BakeryTools
{
    public void UseTool()
    {
        Console.WriteLine("Using bakery tools!");
    }
}

Use Case

  • For reusable components across projects that still need to limit access externally.

  • Used in frameworks or shared libraries where subclassing is common.

6. private protected: The Tightest Inheritance Lock

private protected allows access only by derived classes within the same assembly not by unrelated classes or assemblies. Use it when inheritance is required, but should be restricted within the same project. In real cases, A secured logging mechanism that must be extended only by internal teams.

A secret ingredient shared only among trusted chefs working together in the same kitchen.

Syntax

private protected class SecretIngredient
{
    public void Reveal()
    {
        Console.WriteLine("This ingredient is top secret!");
    }
}

Use Case

  • For critical methods or properties that support inheritance but must remain internal to the project.

  • Helps maintain strict architectural boundaries.

Conclusion

Understanding access modifiers deeply is like mastering the art of controlling the flow of information and responsibilities in a software system. They not only help us write secure code but also make it easier to maintain, extend, and scale our applications. “Choosing the right access modifier is like deciding which door to open, which to lock, and who gets the spare key, It’s what separates a professional developer from someone writing spaghetti(unorganized, and tangled) code!”