C# tutorials > Core C# Fundamentals > Object-Oriented Programming (OOP) > What are access modifiers in C# (public, private, protected, internal, protected internal)?

What are access modifiers in C# (public, private, protected, internal, protected internal)?

Access modifiers are keywords in C# used to specify the declared accessibility of a member. They define the scope from which a member (like a class, method, or variable) can be accessed. Understanding access modifiers is crucial for encapsulation and information hiding, core principles of Object-Oriented Programming (OOP). C# provides five access modifiers: public, private, protected, internal, and protected internal.

Public Access Modifier

The public access modifier allows access from anywhere, both inside and outside the class. It essentially means there are no restrictions on who can access the member. When you need to expose a member to the outside world, public is used.

public class MyClass
{
    public int PublicVariable;

    public void PublicMethod()
    {
        Console.WriteLine("This is a public method.");
    }
}

Private Access Modifier

The private access modifier restricts access to only members within the same class. This is the most restrictive access level and is typically used for internal implementation details that should not be exposed to other parts of the code. This is a cornerstone of encapsulation, hiding the internal workings of your class.

public class MyClass
{
    private int _privateVariable;

    private void PrivateMethod()
    {
        Console.WriteLine("This is a private method.");
    }

    public void AccessPrivateMember()
    {
        _privateVariable = 10; // Accessible from within the class
        PrivateMethod(); // Accessible from within the class
    }
}

Protected Access Modifier

The protected access modifier allows access within the same class and from derived classes, regardless of whether they are in the same assembly or a different one. This is used when you want to allow subclasses to access certain members, but prevent access from outside the inheritance hierarchy.

public class BaseClass
{
    protected int ProtectedVariable;

    protected void ProtectedMethod()
    {
        Console.WriteLine("This is a protected method.");
    }
}

public class DerivedClass : BaseClass
{
    public void AccessProtectedMember()
    {
        ProtectedVariable = 20; // Accessible from derived class
        ProtectedMethod(); // Accessible from derived class
    }
}

Internal Access Modifier

The internal access modifier allows access from within the same assembly (project). Classes and members with internal accessibility are visible to other code within the same compilation unit (e.g., the same .dll or .exe). It's useful for creating helper classes or methods that are only meant to be used internally within your application or library.

internal class MyClass
{
    internal int InternalVariable;

    internal void InternalMethod()
    {
        Console.WriteLine("This is an internal method.");
    }
}

Protected Internal Access Modifier

The protected internal access modifier combines the effects of protected and internal. It allows access from within the same assembly or from derived classes in any assembly. In essence, it's accessible if either the protected or the internal condition is met. If the access happens via an instance of the base class, it must be in the same assembly.

public class BaseClass
{
    protected internal int ProtectedInternalVariable;

    protected internal void ProtectedInternalMethod()
    {
        Console.WriteLine("This is a protected internal method.");
    }
}

public class DerivedClass : BaseClass
{
    public void AccessProtectedInternalMember()
    {
        ProtectedInternalVariable = 30; // Accessible from derived class (even in another assembly)
        ProtectedInternalMethod(); // Accessible from derived class (even in another assembly)
    }
}

public class AnotherClass
{
    public void AccessProtectedInternalMember(BaseClass obj)
    {
        //Only accessible if in the same assembly
        obj.ProtectedInternalVariable = 40;
        obj.ProtectedInternalMethod();
    }
}

Real-Life Use Case Section

Imagine you're building a UI library. You might use public for controls that users of the library can use directly. You would use private for internal properties and methods that manage the control's state but shouldn't be exposed. protected would be used for properties that a derived control can customize. internal might be used for helper classes that are used within the library but not exposed to the outside world. protected internal might be useful for events or properties that a derived control in another assembly can override but are also accessible within the original assembly.

When to use them

  • Public: Use when the member needs to be accessible from any part of the code.
  • Private: Use when the member should only be accessible from within the declaring class.
  • Protected: Use when the member should be accessible from within the declaring class and any derived classes.
  • Internal: Use when the member should be accessible from any code within the same assembly.
  • Protected Internal: Use when the member should be accessible from any code within the same assembly or from derived classes in any assembly.

Best Practices

Favor the most restrictive access modifier that meets your needs. This minimizes the API surface of your classes and makes them easier to maintain. Use private by default and only increase the visibility if necessary. This promotes encapsulation and information hiding.

Interview Tip

Be prepared to explain the differences between all five access modifiers and give examples of when you would use each one. Understand the impact of access modifiers on inheritance and assembly boundaries. Also, understand the difference between protected internal vs either protected or internal alone.

Memory Footprint

Access modifiers themselves do not directly affect the memory footprint of a class or its members. They only control the visibility and accessibility of those members. The size of the class depends on the data types and number of members declared within it, not on their access modifiers.

Alternatives

While access modifiers are the primary way to control access to members, other techniques can be used in conjunction with them or as alternatives in specific scenarios:

  • Interfaces: Define a contract that a class must implement, exposing only the members defined in the interface.
  • Abstract Classes: Provide a base class with some implemented functionality and abstract methods that must be implemented by derived classes. This allows for partial implementation and controlled extension.
  • Friend Assemblies (InternalsVisibleToAttribute): Allow specific assemblies to access internal members of another assembly. This provides more granular control over internal visibility.

Pros and Cons

Pros:

  • Encapsulation: Access modifiers enforce encapsulation by hiding internal implementation details and exposing only necessary members.
  • Information Hiding: They prevent unintended access to sensitive data and methods, improving security and maintainability.
  • Code Reusability: By controlling access, access modifiers promote code reusability and prevent accidental modification of internal state.
  • Maintainability: They make code easier to maintain by reducing dependencies and limiting the scope of changes.

Cons:

  • Complexity: Choosing the right access modifier can add complexity to code, especially in large projects.
  • Over-Restriction: Incorrect use of access modifiers can lead to over-restriction, making it difficult to extend or modify code.
  • Tight Coupling: Overuse of internal members can lead to tight coupling between assemblies, reducing flexibility.

FAQ

  • What happens if I don't specify an access modifier?

    If you don't specify an access modifier for a member of a class, struct, or interface, it defaults to private. However, for members of a namespace, the default is internal.
  • Can I make a top-level class private?

    No, top-level classes can only be public or internal. If a class is private, it wouldn't be accessible from anywhere and would be useless.
  • What is the difference between `protected` and `private protected` in C# 7.2 and later?

    private protected allows access from derived classes within the same assembly. It's like a combination of private and protected, more restrictive than protected and more permissive than private. It isn't covered in the scope of the initial question, but is related.