CodeOath
← All posts
C#65 min total · 17 parts

C# Fundamentals: Value Types, Reference Types, Boxing, and the Type System

Contents — Part 4 of 17: Strings: Immutable Reference Types
Part 4 of 17 · ~1 min

Strings: Immutable Reference Types

string is a reference type, but with one crucial twist: it's immutable. No method on string ever changes it in place — every operation returns a brand-new string.

string s1 = "Hello";
string s2 = s1;
s2 += " World";
Console.WriteLine(s1); // "Hello" — unchanged

s2 += " World" doesn't mutate the string s1 points to — it creates a new string object and repoints s2 at it, leaving s1's original string untouched. The practical consequence: s.Trim(); on its own line does nothing observable, because the returned (trimmed) string is discarded. You have to capture it: s = s.Trim();.

Immutability is also why string is a natural choice for dictionary keys and safe to share freely across threads without locking — nothing can ever change a string out from under a reader. But it comes at a performance cost in code that builds up a string incrementally, since each += allocates an entirely new string and copies the old contents into it:

// O(n²) in the length of the final string — each += reallocates and copies everything so far
string result = "";
for (int i = 0; i < 10000; i++)
{
    result += i.ToString();
}

// The fix: StringBuilder mutates an internal buffer in place, appending in amortized O(1) per call
var sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
    sb.Append(i);
}
string result2 = sb.ToString();