Site

Strings — C# System.String

Tutorial S1  •  C# / Learn

S1.0 What This Teaches

This tutorial covers the C# string type and its operations:

S1.1 Strings are Immutable

string in C# is an alias for System.String. Strings are immutable: every method that appears to modify a string actually returns a new string object:
string s = "Hello";
string upper = s.ToUpper();   // new string "HELLO"
Console.WriteLine(s);         // still "Hello"
Console.WriteLine(upper);     // "HELLO"

// == compares content, not reference
string a = "hello";
string b = "hel" + "lo";
Console.WriteLine(a == b);    // True
Console.WriteLine(ReferenceEquals(a, b));  // may be True due to interning

S1.2 Common String Methods

string text = "  Hello, World!  ";

Console.WriteLine(text.Trim());                    // "Hello, World!"
Console.WriteLine(text.TrimStart());               // "Hello, World!  "
Console.WriteLine(text.Length);                    // 18

string s = "Hello, World!";
Console.WriteLine(s.ToUpper());                    // "HELLO, WORLD!"
Console.WriteLine(s.ToLower());                    // "hello, world!"
Console.WriteLine(s.Contains("World"));            // True
Console.WriteLine(s.StartsWith("Hello"));          // True
Console.WriteLine(s.EndsWith("!"));                // True
Console.WriteLine(s.IndexOf("World"));             // 7
Console.WriteLine(s.Substring(7, 5));              // "World"
Console.WriteLine(s.Replace("World", "C#"));       // "Hello, C#!"

string[] parts = s.Split(", ");                    // ["Hello", "World!"]
string joined = string.Join(" | ", parts);         // "Hello | World!"

S1.3 Interpolation, Verbatim, and Raw String Literals

string name = "Alice";
int age = 30;

// Interpolated string
string msg = $"Name: {name}, Age: {age}";

// Format specifiers inside interpolation
double pi = Math.PI;
Console.WriteLine($"Pi = {pi:F4}");   // Pi = 3.1416

// Verbatim string - backslashes are literal
string path = @"C:\Users\Alice\Documents";

// Raw string literal (C# 11) - no escape sequences at all
string json = """
    {
        "name": "Alice",
        "age": 30
    }
    """;
Console.WriteLine(json);

S1.4 String Comparison

Always specify a StringComparison when the comparison must be culture-aware or case-insensitive. The default == is ordinal and case-sensitive:
string a = "Hello";
string b = "hello";

Console.WriteLine(a == b);   // False (case-sensitive)
Console.WriteLine(string.Equals(a, b, StringComparison.OrdinalIgnoreCase));  // True

// Sort order comparison
int cmp = string.Compare("apple", "Banana", StringComparison.OrdinalIgnoreCase);
Console.WriteLine(cmp);   // negative - "apple" comes first

S1.5 StringBuilder

Concatenating strings in a loop with + creates a new string object each iteration. StringBuilder builds into a mutable buffer and is O(n) instead of O(n²):
using System.Text;

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5; i++)
{
    sb.Append($"item{i}");
    if (i < 4) sb.Append(", ");
}
string result = sb.ToString();
Console.WriteLine(result);   // item0, item1, item2, item3, item4

sb.Clear();
sb.AppendLine("line 1");
sb.AppendLine("line 2");
Console.Write(sb);

S1.6 Example - All Together

// Strings - word frequency counter using string operations.

using System.Text;

string text = "the quick brown fox jumps over the lazy dog the fox";
string[] words = text.Split(' ');
var freq = new Dictionary<string, int>();

foreach (string w in words)
    freq[w] = freq.GetValueOrDefault(w, 0) + 1;

var sorted = freq.OrderByDescending(kv => kv.Value).Take(5);

var sb = new StringBuilder("Top words:\n");
foreach (var (word, count) in sorted)
    sb.AppendLine($"  {word,-10} {count}");

Console.Write(sb);
Expected output:
Top words:
  the        3
  fox        2
  quick      1
  brown      1
  jumps      1

S1.7 Exercise

Exercise
  • Write a method that takes a sentence and returns it in title case (first letter of each word capitalized). Use Split, string.Join, and char.ToUpper.
  • Write a method that checks if a string is a palindrome ignoring spaces and case. Use Replace, ToLower, and array reversal.
  • Use StringBuilder to generate a CSV string from a list of tuples (string Name, int Score).

S1.8 Common Mistakes

Using + in loops for concatenation

result += piece inside a loop creates a new string on each iteration. For more than a few iterations, use StringBuilder or string.Join.

Comparing with == without specifying culture

== is ordinal and case-sensitive. Use string.Equals(a, b, StringComparison.OrdinalIgnoreCase) when you need case-insensitive comparison, and avoid ToLower() == which allocates.

Off-by-one in Substring

string s = "Hello";
Console.WriteLine(s.Substring(1, 3));  // "ell" - start=1, length=3
// s[1..4] with range syntax is often clearer: s[1..4] = "ell"

S1.9 Key Terms

TermMeaning
immutableString content cannot change after creation; all methods return new strings
string interpolation$"..." embeds expressions directly in a string literal
verbatim string@"..." treats backslashes as literal characters
raw string literal"""...""" (C# 11) - no escape sequences; whitespace is literal
StringBuilderMutable buffer for building strings efficiently in loops
StringComparisonEnum controlling culture and case sensitivity in comparisons
Span<char>Zero-allocation window into string memory for slicing
string interningRuntime reuse of identical string literals from a pool