<style> .reveal-up, .reveal-left, .reveal-right, .reveal-stagger > * { opacity: 1 !important; transform: none !important; } </style>
  1. Learn
  2. C#
  3. Object-oriented programming
All lessons in this course

Lesson 20 of 60 12 minIntermediate

Access modifiers and encapsulation

Decide who can use each part of your class with public, private, protected and internal, and design classes that are hard to misuse.

Encapsulation means hiding the inner workings of a class and exposing only a small, safe set of members. Think of a car: you use the steering wheel and pedals (the public part); the engine internals are hidden. You can drive without knowing them, and you can’t accidentally break them.

Access modifiers are the keywords that control who can see each class and member.

Interactive

Who can see this member?

Choose a modifier for Beam.Length. Green places may use it; red ones get a compile error.

privatedouble Length;
  • Inside the same class✓ allowed
  • Derived class, same project✗ CS0122
  • Any other class, same project✗ CS0122
  • Derived class, other project✗ CS0122
  • Any class, other project✗ CS0122
Only code inside the same class. The default for members, and the right choice for fields.

The ones you will use 95% of the time

ModifierAccessible fromTypical use
publiceverywherethe methods and properties other code is meant to use
privateonly the same classfields and helper methods
protectedthe class and classes that inherit from itmembers subclasses need to customise behaviour
internalanywhere in the same project (assembly)classes shared inside a library but hidden from users of it

Encapsulation in practice

BankAccount.cs
public class BankAccount{    private decimal _balance;                       // hidden state    private readonly List<string> _history = new();     public string Owner { get; }    public decimal Balance => _balance;             // read-only view     public BankAccount(string owner) => Owner = owner;     public void Deposit(decimal amount)    {        if (amount <= 0) throw new ArgumentException("Amount must be positive.");        _balance += amount;        Log($"Deposit {amount}");    }     public bool TryWithdraw(decimal amount)    {        if (amount <= 0 || amount > _balance) return false;        _balance -= amount;        Log($"Withdraw {amount}");        return true;    }     private void Log(string entry) => _history.Add($"{DateTime.Now:HH:mm} {entry}");} var acc = new BankAccount("Ravi");acc.Deposit(1000);Console.WriteLine(acc.TryWithdraw(5000));   // False: rule enforcedConsole.WriteLine(acc.Balance);// acc._balance = 1_000_000;                // error CS0122: inaccessible
Output
False
1000

There is no way for outside code to put the account into a wrong state: the balance can only change through Deposit and TryWithdraw, which apply the rules. If the rules change later, you edit one class, not every place that uses it.

readonly fields

A readonly field can be assigned only in its declaration or in a constructor. In the example, _history always refers to the same list (though the list’s contents can still change).

Guidelines

  • Start with everything private; make something more visible only when another class truly needs it.
  • Never make fields public. Use properties.
  • Expose operations (Deposit) rather than raw setters (SetBalance).
  • A small public surface means fewer ways to misuse the class and more freedom to change its internals.
Quick check

What is the access level of a class member declared without a modifier?

Quick check

A protected member can be used by…

Practice

Write a class Counter with a private count, a public read-only property Value, and public methods Increment(), Decrement() (never below 0) and Reset(). Show that Decrement at 0 keeps the value at 0.

Show the solution
Solution.cs
public class Counter{    private int _count;    public int Value => _count;     public void Increment() => _count++;    public void Decrement() { if (_count > 0) _count--; }    public void Reset() => _count = 0;} var c = new Counter();c.Increment(); c.Increment(); c.Decrement(); c.Decrement(); c.Decrement();Console.WriteLine(c.Value);
Output
0

Remember

  • Encapsulation: hide state, expose a small set of safe operations.
  • private (class only), protected (+ subclasses), internal (same project), public (all).
  • Members are private by default; classes are internal by default.
  • Keep fields private and change state only through validated methods.
0 of 60 lessons completed