0Pricing
C# Academy · Lesson

Encapsulation & invariants

Hide internal state, expose safe operations, and keep class invariants true (e.g., non-negative balance, valid ranges).

Encapsulation & invariants is a free C# Academy lesson on CoddyKit — lesson 3 of 3. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, one of 3 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Encapsulation overview

Goal: Protect your object’s state.

  • Encapsulation: hide fields, expose safe APIs
  • Invariant: a rule that is always true
  • Validate in constructors/setters/methods

Read-only surface

Keep fields private. Give callers a read-only property and safe operations.

using System;

// Expose read-only view; mutate via methods only
public class Counter
{
  private int _value;          // hidden state
  public int Value             // read-only to callers
  {
    get { return _value; }
    private set { _value = value; } // keep setter private
  }

  public void Increment()
  {
    Value = Value + 1;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Counter c = new Counter();
    c.Increment();
    c.Increment();
    Console.WriteLine("Value = " + c.Value);
  }
}

Constructor guards

Constructors set required state. Guard against invalid inputs to keep objects valid from the start.

using System;

// Enforce rules early (constructor guard)
public class User
{
  public string Name { get; private set; }
  public int Age { get; private set; }

  public User(string name, int age)
  {
    if (string.IsNullOrEmpty(name)) throw new ArgumentException("name");
    if (age < 0) throw new ArgumentOutOfRangeException("age");
    Name = name;
    Age = age;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    try
    {
      User u = new User("Ada", 28);
      Console.WriteLine(u.Name + " (" + u.Age + ")");
    }
    catch (Exception ex)
    {
      Console.WriteLine("Error: " + ex.Message);
    }
  }
}

Invariant in practice

Define an invariant (e.g., Balance ≥ 0) and enforce it in setters and methods.

using System;

// Invariant: Balance >= 0 at all times
public class BankAccount
{
  private decimal _balance;

  public decimal Balance
  {
    get { return _balance; }
    private set
    {
      if (value < 0) throw new InvalidOperationException("Balance would be negative");
      _balance = value;
    }
  }

  public BankAccount(decimal opening)
  {
    if (opening < 0) throw new ArgumentOutOfRangeException("opening");
    _balance = opening;
  }

  public void Deposit(decimal amount)
  {
    if (amount <= 0) throw new ArgumentOutOfRangeException("amount");
    Balance = Balance + amount;
  }

  public bool TryWithdraw(decimal amount)
  {
    if (amount <= 0) return false;
    if (Balance - amount < 0) return false;
    Balance = Balance - amount;
    return true;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    BankAccount a = new BankAccount(50m);
    a.Deposit(20m);
    bool ok = a.TryWithdraw(100m); // fails, invariant protected
    Console.WriteLine("ok=" + ok + " balance=" + a.Balance);
  }
}

Protect collections

Do not expose internal lists/arrays directly. Return a copy (or a read-only view) to protect invariants.

using System;
using System.Collections.Generic;

public class Tags
{
  private readonly List<string> _items = new List<string>();

  public void Add(string tag)
  {
    if (string.IsNullOrWhiteSpace(tag)) return;
    _items.Add(tag.Trim());
  }

  // Expose a copy so callers cannot mutate internal list
  public List<string> GetAllCopy()
  {
    return new List<string>(_items);
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Tags t = new Tags();
    t.Add(" apple ");
    t.Add("banana");
    List<string> view = t.GetAllCopy();
    view.Add("hacker"); // modifies the copy only
    Console.WriteLine("copy count=" + view.Count);
    Console.WriteLine("original count=" + t.GetAllCopy().Count);
  }
}

Encapsulation tips

Checklist:

  • Private fields; public properties/methods.
  • Validate in constructor/setters.
  • Keep invariants true after every call.
  • Do not leak internal collections.

Encapsulation principle

Quick check: Which choice best preserves encapsulation and a class invariant?

Recap

Recap: Encapsulate with private fields and validated APIs. Define an invariant and enforce it in constructors, setters, and methods. Never leak internal collections.

Frequently asked questions

Is the “Encapsulation & invariants” lesson free?

Yes — the full text of “Encapsulation & invariants” is free to read here on the web, and the C# Academy course includes 3 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO.

What will I learn in “Encapsulation & invariants”?

Hide internal state, expose safe operations, and keep class invariants true (e.g., non-negative balance, valid ranges). You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 3, so you can start here or from the beginning and move at your own pace.

How long does the “Encapsulation & invariants” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Fields, auto-properties, object initializers
  2. Constructors, static members
  3. Encapsulation & invariants
← Back to C# Academy