Skip to content

Intermediate · Classes and objects · topic 16 of 43 · 30 min

Access modifiers, static members and encapsulation

Explanation

Encapsulation means keeping an object's data private and letting outside code change it only through safe methods. Access modifiers (public, private, protected, internal) decide who can see each member; class members are private unless you say otherwise. static members belong to the class itself and are shared by all objects, like a counter of how many accounts exist.

Encapsulation: protect the data

Encapsulation is one of the main ideas of OOP. An object hides its data and exposes only the actions that keep it valid. A bank account should never have a negative balance by accident, so the balance is private and the only way to change it is Deposit or Withdraw, which check the rules.

Think of it like this: An ATM is encapsulation in steel. You cannot open the machine and take notes out by hand. You can only use the buttons (public methods), and the machine checks your PIN and balance before giving cash. The cash inside is private.

Access modifiers

ModifierWho can use the member
publicAny code, anywhere
privateOnly code inside the same class (the default for class members)
protectedThe same class and classes that inherit from it (module 5)
internalAny code in the same project / assembly (the default for top-level classes)
protected internalThe same project, OR derived classes anywhere
private protectedDerived classes that are also in the same project

An assembly is the .dll your project builds. internal is useful for helper classes that other projects should not depend on.

csharp
public class BankAccount
{
    private decimal _balance;                 // hidden
    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;
    }

    public bool TryWithdraw(decimal amount)
    {
        if (amount <= 0 || amount > _balance) return false;
        _balance -= amount;
        return true;
    }
}
Outside code cannot write _balance. Every change passes through a method that checks the rules.

static members: shared by the whole class

Normally each object has its own fields. A static field belongs to the class itself, so there is only one copy, shared by all objects. A static method belongs to the class too, so you call it on the class name, without creating an object. Math.Max and Console.WriteLine are static methods.

csharp
var t1 = new Ticket("Asha");
var t2 = new Ticket("Ravi");
Console.WriteLine($"{t1.No} {t2.No}");         // 1001 1002
Console.WriteLine(Ticket.IssuedSoFar);         // 2

class Ticket
{
    private static int _nextNo = 1001;     // one counter for all tickets
    public int No { get; }
    public string Passenger { get; }

    public Ticket(string passenger)
    {
        Passenger = passenger;
        No = _nextNo++;                     // use, then increase
    }

    public static int IssuedSoFar => _nextNo - 1001;
}
The static counter is shared, so each new ticket gets the next number.
Careful: A static method cannot use instance fields or this, because it is not called on any particular object. Trying to gives error CS0120. Also, static fields that change are shared by every user of a web server at once, which causes bugs; prefer them for constants and counters you understand.

static classes

csharp
Console.WriteLine(Gst.Add(1000m));   // 1180.00

public static class Gst
{
    public const decimal StandardRate = 0.18m;
    public static decimal Add(decimal amount, decimal rate = StandardRate) => amount + amount * rate;
}
A static class cannot be created with new and holds only static members. Use it for helper functions, like Math.

const, readonly and static readonly

KeywordSet when?Example
constAt compile time; must be a literal valueconst int MaxSeats = 72;
readonly fieldIn its declaration or the constructor; then fixed for that objectprivate readonly string _accountNo;
static readonlyOnce for the whole class, when the program starts using itstatic readonly DateTime Started = DateTime.Now;

Common mistakes and fixes

  • Making everything public "to make it work": you lose the protection. Start with private and open up only what callers truly need.
  • Forgetting that members are private by default: void Deposit() inside a class cannot be called from outside. Add public.
  • Using a static field for per-user data like the "current user": every object and every request shares it. Use an instance field instead.
  • Trying to new a static class: error. Call its members on the class name.
Tip: A good test for encapsulation: can outside code put your object into an invalid state? If yes, make that member private and add a method that checks the rules.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Access modifiers, static members and encapsulation · 1/7

Encapsulation

In this lesson you will protect your objects with encapsulation.

Prefer a video by a teacher? Find free videos on “C# access modifiers static members encapsulation explained” on YouTube ↗

In real life: A metro smart card

A metro card stores a balance. Riders can recharge it and the gate deducts fares, but no app or person can set the balance directly. A static fare table is shared by every card.

csharp
var card = new MetroCard("MC-7781");
card.Recharge(200m);
Console.WriteLine(card.TryTapOut(stations: 6) ? $"Paid. Left: {card.Balance}" : "Low balance");

public class MetroCard
{
    private decimal _balance;
    public string CardNo { get; }
    public decimal Balance => _balance;

    public MetroCard(string cardNo) => CardNo = cardNo;

    public void Recharge(decimal amount)
    {
        if (amount < 50m) throw new ArgumentException("Minimum recharge is 50");
        _balance += amount;
    }

    public bool TryTapOut(int stations)
    {
        decimal fare = Fare(stations);
        if (fare > _balance) return false;
        _balance -= fare;
        return true;
    }

    public static decimal Fare(int stations) => stations switch
    {
        <= 2 => 10m,
        <= 5 => 20m,
        <= 12 => 30m,
        _ => 40m
    };
}
Shows Paid. Left: 170. Real metro fares differ by city; these numbers are for practice.

Practice (0/4 done)

Task 1 · Question

What is the default access level of a method declared in a class without a modifier?

Task 2 · Question

What does this print? var a = new Box(); var b = new Box(); var c = new Box(); Console.WriteLine(Box.Count); class Box { public static int Count; public Box() { Count++; } }

Task 3 · Question

Why does a static method fail when it reads an instance field?

Task 4 · Practice

Design a class WalletAccount for a payments app. The balance must be private. Add AddMoney(decimal), TryPay(decimal amount, string to) that fails if the balance is too low, and a read-only Balance property. Add a static field that counts how many wallets were created, with a static property to read it.

Quick quiz

Question 1

1.What is encapsulation?

Question 2

2.Who can access an internal class?

Question 3

3.How do you call a static method Fare on class MetroCard?

Question 4

4.Which can be set only in its declaration or the constructor?

Question 5

5.Can you write new Math()?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What is encapsulation?

Answer: Hiding an object's data and allowing changes only through controlled members

Encapsulation protects an object's data and rules.

Who can access an internal class?

Answer: Any code in the same assembly (project)

internal means visible inside the same assembly.

How do you call a static method Fare on class MetroCard?

Answer: MetroCard.Fare(3)

Static members are reached through the class name.

Which can be set only in its declaration or the constructor?

Answer: a readonly field

readonly fields become fixed once construction finishes.

Can you write new Math()?

Answer: No, Math is a static class

Static classes cannot be instantiated.

A static member variable is…Related

Answer: shared by the whole class, one copy in total

Static members belong to the class, not to individual objects.

From Classes and objects: data plus behaviour

What is encapsulation?Related

Answer: Hiding data and exposing behaviour through methods that enforce rules

Objects protect their own state.

From Encapsulation: private fields, getters and setters

What makes a class field private?Related

Answer: A leading #

#name fields are truly private; _name is only a naming convention.

From Classes

How do you usually call a static method?Related

Answer: ClassName.method()

Static members belong to the class.

From static members and final

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Classes and objects” before its exam: Structs, value types and reference types.
  2. Module 4 exam: Classes and objects · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Inheritance, interfaces and records. 43 topics left in the course before the final exam.

← Previous: Properties: get, set, init and required