LearnAI ToolsCareerPractice BuildsPlayDevelopmentContact
Lesson 1618 min read

Strings

Learn how to work with strings in C# — concatenation, interpolation, common methods, and StringBuilder.

C# & .NET learning pathLesson 16 of 66
View course
On this page 10 sections

Strings Are Immutable

Once a string is created, it can never be changed for the rest of its lifetime. Every method that appears to modify a string — like ToUpper() or Replace() — actually returns a brand new string object, leaving the original completely untouched.

string original = "hello";
string upper = original.ToUpper();
Console.WriteLine(original); // "hello" — unchanged
Console.WriteLine(upper); // "HELLO" — a new string

Common String Methods

MethodPurpose
.LengthNumber of characters
.ToUpper() / .ToLower()Change case
.Trim() / .TrimStart() / .TrimEnd()Remove leading/trailing whitespace
.Substring(start, length)Extract part of a string
.Split(char)Split into an array of strings
.Replace(old, new)Replace all occurrences of a substring
.Contains(value)Check if a substring exists
.StartsWith() / .EndsWith()Check the beginning or end of a string
.IndexOf(value)Find the position of a substring, or -1 if not found
.PadLeft(n) / .PadRight(n)Pad a string to a fixed width
string sentence = " Hello, C# World! ";
Console.WriteLine(sentence.Trim().ToUpper());
Console.WriteLine(sentence.Contains("C#"));
Console.WriteLine(sentence.Trim().StartsWith("Hello"));
Console.WriteLine("7".PadLeft(3, '0')); // "007"
Output

Click Run to see what this code prints.

Concatenation & Interpolation

As covered in the input/output lesson, string interpolation is the modern, preferred approach — it reads more naturally and handles formatting and alignment directly, without the visual clutter of many + operators.

string first = "Jane";
string last = "Doe";
string full1 = first + " " + last; // concatenation — works, but less readable at scale
string full2 = $"{first} {last}"; // interpolation (preferred)
Console.WriteLine(full2);

Comparing Strings

Unlike most reference types, == on strings compares their actual content, not just whether they're the same object in memory — a deliberate, useful exception to normal reference-type equality behavior.

string a = "hello";
string b = "HELLO";
Console.WriteLine(a == b); // False — case-sensitive by default
Console.WriteLine(string.Equals(a, b, StringComparison.OrdinalIgnoreCase)); // True
Fun Fact

string.Equals with an explicit StringComparison argument is generally considered best practice over == in production code, since it forces you to consciously decide whether the comparison should be case-sensitive, culture-aware, or ordinal — a decision == silently makes for you (case-sensitive, ordinal) without making that choice visible.

Splitting & Joining

Split() breaks a string into an array based on a delimiter; string.Join() does the reverse, combining an array (or any collection) back into one string with a separator.

string csv = "Alice,Bob,Charlie";
string[] names = csv.Split(',');
Console.WriteLine(names.Length); // 3
Console.WriteLine(names[1]); // Bob
string rejoined = string.Join(" & ", names);
Console.WriteLine(rejoined); // Alice & Bob & Charlie

StringBuilder

Because strings are immutable, building one up in a loop with += creates a brand new string object on every single iteration — for a small number of iterations this is invisible, but for hundreds or thousands, it wastes significant memory and time. StringBuilder mutates an internal, resizable buffer instead, which is far more efficient for repeated appends.

using System.Text;
var sb = new StringBuilder();
for (int i = 1; i <= 3; i++)
{
sb.Append($"Line {i}\n");
}
Console.WriteLine(sb.ToString());
When to Use StringBuilder

Reach for StringBuilder when building a string inside a loop with many iterations (dozens or more). For a handful of concatenations, regular strings and interpolation are perfectly fine and more readable — StringBuilder itself has a small amount of overhead that isn't worth it for trivial cases.

StringBuilder also supports several other useful methods beyond Append.

MethodPurpose
.Append(value)Adds text to the end
.AppendLine(value)Adds text followed by a newline
.Insert(index, value)Inserts text at a specific position
.Remove(start, length)Removes a range of characters
.Replace(old, new)Replaces text within the buffer
.ToString()Converts the buffer to a final, regular string

Common Beginner Mistakes

Expecting a string method to modify the original variable

text.Trim(); on its own does nothing useful — the result must be captured: text = text.Trim();, since strings can never be modified in place.

Building a large string with += inside a loop

This creates a new string object on every iteration — use StringBuilder for anything beyond a small, fixed number of concatenations.

Assuming string comparison is always case-insensitive

== and string.Equals() default to case-sensitive comparison — explicitly pass StringComparison.OrdinalIgnoreCase when case shouldn't matter.

FAQs

Use string.Equals(a, b, StringComparison.OrdinalIgnoreCase) rather than converting both to the same case first with ToUpper()/ToLower(), which creates unnecessary intermediate string objects.

Conceptually yes — interpolation ($"...") is newer, more readable syntax that compiles down to essentially the same mechanism as string.Format("{0}", value); both support the same format specifiers.

It throws an ArgumentOutOfRangeException — always ensure start + length doesn't exceed the string's actual Length before calling Substring on untrusted input.

Yes — "" is a valid, zero-length string object; null means no string object exists at all. string.IsNullOrEmpty() and string.IsNullOrWhiteSpace() check for both cases at once, which is usually what you actually want.

Key Takeaways

  • Strings are immutable — every "modifying" method returns a new string, never changing the original.
  • Prefer string interpolation ($"...") over manual + concatenation for readability.
  • Use string.Equals with an explicit StringComparison for comparisons where case-sensitivity matters.
  • Use StringBuilder for building large strings inside loops with many iterations.

Summary

Strings are one of the most frequently used types in any real program, and understanding their immutability — plus when to reach for StringBuilder — will make your code both correct and efficient. Next, you'll learn how to organize reusable logic into methods.

Next Lesson →

Methods