Codectionary / Developer documentation / C#

Access Modifiers

Access modifiers control the visibility of classes, fields, methods, and properties from other parts of a program. C# provides public (accessible from anywhere), private (accessible only within the declaring class - the default for class members), protected (accessible within the class and its subclasses), internal (accessible only within the same assembly/project), and combinations like protected internal and private protected.

Read the syntax

public permits access from other code; private restricts access to the declaring type. internal limits access to the same assembly, while protected permits access within a type and its derived types.

Access modifiers describe where members may be used, not whether their values are valid. Expose controlled operations or properties instead of making mutable implementation fields public.

Syntax

public | private | protected | internal

Examples

The Main Access Levels

Demonstrating the most commonly used modifiers on fields within a class.

public class AccessDemo
{
    public int PublicField = 1;        // accessible from anywhere
    protected int ProtectedField = 2;   // accessible in this class + subclasses
    internal int InternalField = 3;      // accessible within the same project
    private int privateField = 4;         // accessible only within this class

    private void ShowAll()
    {
        // all four are accessible from inside the class itself
        Console.WriteLine(PublicField + ProtectedField + InternalField + privateField);
    }
}
  1. Demonstrating the most commonly used modifiers on fields within a class.
  2. public permits access from other code; private restricts access to the declaring type. internal limits access to the same assembly, while protected permits access within a type and its derived types.
  3. The class declares four differently accessible fields. ShowAll could read all four from inside AccessDemo, but nothing calls this private method, so this snippet prints nothing.

Private Fields with Public Properties

The standard encapsulation pattern: hide data, expose controlled access through a property.

Account acc = new Account(100);
// acc._balance = -500;  // Error - private, can't be accessed directly
acc.Deposit(50);
Console.WriteLine(acc.Balance);  // 150

public class Account
{
    private double _balance;  // hidden from outside access

    public Account(double initialBalance)
    {
        _balance = initialBalance;
    }

    public double Balance => _balance;  // controlled read access

    public void Deposit(double amount)
    {
        if (amount > 0)
        {
            _balance += amount;
        }
    }
}
  1. The standard encapsulation pattern: hide data, expose controlled access through a property.
  2. public permits access from other code; private restricts access to the declaring type. internal limits access to the same assembly, while protected permits access within a type and its derived types.
  3. Account hides _balance and exposes a getter plus Deposit. The valid deposit raises 100 to 150, which Balance prints; the commented direct assignment cannot compile.

protected and Inheritance

protected members are accessible to subclasses, even outside the original assembly.

Car car = new Car();
car.Drive();  // Speed: 10

public class Vehicle
{
    protected int Speed;

    protected void Accelerate()
    {
        Speed += 10;
    }
}

public class Car : Vehicle
{
    public void Drive()
    {
        Accelerate();  // accessible because Car extends Vehicle
        Console.WriteLine($"Speed: {Speed}");
    }
}
  1. protected members are accessible to subclasses, even outside the original assembly.
  2. public permits access from other code; private restricts access to the declaring type. internal limits access to the same assembly, while protected permits access within a type and its derived types.
  3. Car inherits Vehicle and can call its protected Accelerate method. Drive adds 10 to Speed and prints Speed: 10; unrelated code cannot access Speed directly.

Best practices

  • Default to private for fields, exposing access only through public properties when genuinely needed (encapsulation)
  • Use internal for types and members that should only be used within your own project/library, not exposed to external consumers
  • Use protected specifically when subclasses need access, and public only for the intentional external API of a class
  • Avoid the temptation to make everything public "just in case" - it removes the safety encapsulation is meant to provide

Runtime & versions

.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

C# language reference

Specifications & further reading