Mutable vs. Immutable

C# / .NET Interview Notes


1. Big Picture

In C#, every type is either mutable (can change after creation) or immutable (cannot change after creation). Understanding this distinction is fundamental to writing correct, thread-safe, and predictable code.

⭐ Quick Memory Trick:
Mutable → "I can change" (List, StringBuilder, class instances)
Immutable → "I am set in stone" (string, int, record)

2. Value Types vs Reference Types

C# has two categories of types, and mutability interacts with both:

Value Types (struct, enum, primitive)

Stored directly on the stack (or inline in a containing object). Copied by value — assigning creates a new copy.

int a = 5;
int b = a;  // b is a COPY of a
b = 10;     // a is still 5

Console.WriteLine(a);  // 5
Console.WriteLine(b);  // 10

Reference Types (class, interface, delegate, array)

Stored on the heap. Variables hold a reference (pointer) to the data. Assigning copies the reference, not the data.

var list1 = new List<int> { 1, 2, 3 };
var list2 = list1;  // list2 points to SAME list
list2.Add(4);

Console.WriteLine(list1.Count);  // 4 — list1 changed too!
Console.WriteLine(list2.Count);  // 4

3. Immutable Types in C#

string

The most famous immutable type. Every "modification" creates a new string:

string s = "hello";
s = s + " world";  // NEW string object created
s.ToUpper();        // returns NEW string, s unchanged

Console.WriteLine(s);  // "hello" — unchanged!
⚠️ Common Trap: s.ToUpper() does NOT modify s. You must assign: s = s.ToUpper().

All primitive types

int, double, bool, char, DateTime, etc. are all immutable. Operations return new values.

record

Reference type with immutable-by-default semantics and value-based equality:

record Person(string Name, int Age);

var p1 = new Person("Alice", 30);
var p2 = p1 with { Age = 31 };  // NEW record, p1 unchanged

Console.WriteLine(p1.Age);  // 30
Console.WriteLine(p2.Age);  // 31

4. Mutable Types in C#

List<T>

var list = new List<int> { 1, 2, 3 };
list.Add(4);        // mutates in place
list.RemoveAt(0);   // mutates in place
list[0] = 99;       // mutates in place

StringBuilder

Mutable alternative to string for heavy manipulation:

var sb = new StringBuilder("hello");
sb.Append(" world");   // mutates in place
sb.Replace("world", "there");
Console.WriteLine(sb.ToString());  // "hello there"

Class instances

class Counter { public int Count { get; set; } }

var c = new Counter { Count = 0 };
c.Count++;  // mutates the object

5. Why Immutability Matters

Thread Safety

Immutable objects are inherently thread-safe — no locks needed because nothing can change.

Predictability

No side effects from unexpected mutations. Easier to reason about code.

Hash Code Stability

Immutable objects can cache their hash code. Mutable objects in hash collections cause bugs:

// DANGER: mutable key in HashSet
var dict = new Dictionary<StringBuilder, int>();
var key = new StringBuilder("hello");
dict[key] = 1;
key.Append(" world");  // hash code changes — key is now lost!

6. readonly and init

readonly fields

class Config
{
    public readonly string Name;
    public Config(string name) { Name = name; }  // set once in constructor
}

init-only setters (C# 9+)

class Person
{
    public string Name { get; init; }  // set at creation, then frozen
}

var p = new Person { Name = "Alice" };
// p.Name = "Bob";  // compile error!

7. Defensive Copying

When you must expose mutable data, return a copy to protect internal state:

class Team
{
    private List<string> _members = new();

    public IReadOnlyList<string> Members => _members.AsReadOnly();

    public void AddMember(string name) => _members.Add(name);
}

8. Common Interview Questions

Q: Why is string immutable?

Security (no tampering after creation), thread safety, hash code caching, and string interning (memory optimization).

Q: What is the difference between readonly and const?

const is compile-time constant (must be set at declaration). readonly is runtime constant (can be set in constructor).

Q: How do you make a class immutable?

Make all fields readonly, use get-only properties, don't expose mutable collections, and return copies of any mutable data.


9. One-Line Interview Answer

Mutable types can be changed after creation (List, StringBuilder, class instances), while immutable types cannot (string, int, record). Immutability provides thread safety, predictability, and hash code stability — and C# offers readonly, init-only setters, and records to enforce it.