Working with strings
Build, inspect and transform text with string methods, interpolation and StringBuilder.
12 min read
You will learn
- Access characters and lengths of strings
- Use the most common string methods
- Format values with interpolation and format specifiers
- Understand why strings are immutable and when to use StringBuilder
Strings are sequences of characters
A string holds text. Under the hood it's a sequence of char values that you can inspect:
string word = "C# rocks";
Console.WriteLine(word.Length); // 8
Console.WriteLine(word[0]); // 'C' — indexes start at 0
Console.WriteLine(word[^1]); // 's' — ^1 means "first from the end"
Console.WriteLine(word[3..]); // "rocks" — a range from index 3 to the endStrings are immutable
Once created, a string never changes. Methods that seem to modify a string actually return a new one:
string name = "ada";
name.ToUpper(); // creates "ADA"… and throws it away
Console.WriteLine(name); // ada
name = name.ToUpper(); // keep the result
Console.WriteLine(name); // ADAWatch out
Forgetting to use the returned value is a very common bug: text.Trim(); on its own line does nothing useful.
The methods you'll use constantly
| Method | Example | Result |
|---|---|---|
ToUpper() / ToLower() | "Hi".ToUpper() | "HI" |
Trim() | " hi ".Trim() | "hi" |
Contains(x) | "hello".Contains("ell") | true |
StartsWith(x) / EndsWith(x) | "file.cs".EndsWith(".cs") | true |
IndexOf(x) | "hello".IndexOf('l') | 2 (or -1 if missing) |
Substring(start, length) | "hello".Substring(1, 3) | "ell" |
Replace(a, b) | "a-b-c".Replace("-", "") | "abc" |
Split(sep) | "a,b,c".Split(',') | ["a", "b", "c"] |
string.Join(sep, items) | string.Join("-", parts) | "a-b-c" |
string.IsNullOrWhiteSpace(s) | string.IsNullOrWhiteSpace(" ") | true |
And for single characters, the char type has helpers: char.ToUpper(c), char.IsDigit(c), char.IsLetter(c).
To repeat a character, use new string('*', 5) → "*****".
Building strings
Concatenation with + works, but interpolation is clearer:
string first = "Ada", last = "Lovelace";
int born = 1815;
string a = "Name: " + first + " " + last + " (" + born + ")";
string b = $"Name: {first} {last} ({born})"; // same result, easier to readFormat specifiers
Inside { }, add a colon and a format:
double price = 1234.5;
Console.WriteLine($"{price:F2}"); // 1234.50 — 2 decimals
Console.WriteLine($"{price:N0}"); // 1,235 — thousands separator, no decimals
Console.WriteLine($"{0.256:P1}"); // 25.6 % — percentage
Console.WriteLine($"{42,6}|"); // 42| — right-aligned in 6 characters
Console.WriteLine($"{DateTime.Now:yyyy-MM-dd}");Special characters and multi-line text
string tab = "Name:\tAda"; // \t tab, \n new line, \" quote, \\ backslash
string path = @"C:\Users\Ada\file.txt"; // verbatim: backslashes are literal
string json = """
{
"name": "Ada",
"born": 1815
}
"""; // raw string literal: no escaping at allComparing strings
== compares the text, which is what you want most of the time. For case-insensitive comparison:
bool same = string.Equals("Hello", "HELLO", StringComparison.OrdinalIgnoreCase); // trueStringBuilder for building in loops
Because strings are immutable, += in a loop creates a new string every time. For many appends, use StringBuilder:
using System.Text;
var sb = new StringBuilder();
for (int i = 1; i <= 5; i++)
{
sb.Append(i).Append(' ');
}
Console.WriteLine(sb.ToString()); // "1 2 3 4 5 "Try it
C# runtime not loaded
Key takeaways
- Strings are immutable: methods return new strings — keep the result.
- Index with
s[0],s[^1], and ranges likes[1..4]. - Prefer interpolation
$"..."and use format specifiers like:F2and:N0. - Use
StringBuilderwhen building text piece by piece in a loop.
Exercise
Implement Initials ("ada", "lovelace" → "A.L."), FormatName which trims spaces and capitalizes only the first letter (" aDA " → "Ada"), and Mask which hides all but the last four characters of a card number ("1234567812345678" → "************5678").
C# runtime not loaded
Hint 1
Get a character with an index: first[0]. char.ToUpper(c) uppercases a single character.
Hint 2
For FormatName: Trim() first, then combine char.ToUpper(t[0]) with t.Substring(1).ToLower().
Hint 3
new string('*', count) repeats a character. cardNumber.Substring(cardNumber.Length - 4) gives the last four.
Show solution
string Initials(string first, string last) =>
$"{char.ToUpper(first[0])}.{char.ToUpper(last[0])}.";
string FormatName(string name)
{
string trimmed = name.Trim();
return char.ToUpper(trimmed[0]) + trimmed.Substring(1).ToLower();
}
string Mask(string cardNumber) =>
new string('*', cardNumber.Length - 4) + cardNumber.Substring(cardNumber.Length - 4);
Console.WriteLine(Initials("ada", "lovelace"));
Console.WriteLine(FormatName(" aDA "));
Console.WriteLine(Mask("1234567812345678"));Quiz
4 questions · 3 correct to pass1.What does `"hello".ToUpper()` do to the original string?
2.What is `"C# rocks".Length`?
3.Which line prints a price as `$19.99`-style currency with two decimals?
4.When should you use StringBuilder?
To complete this lesson
- ○ Solve the exercise
- ○ Pass the quiz (3/4 correct)