Skip to content

Chapter 6 of 7

Memory, Performance, and Strings

Modern C# provides several types for working with memory directly while avoiding garbage collector pressure. Span is a ref struct representing a contiguous region of memory, such as an array, a string slice, or stack-allocated memory, and it enables zero-allocation slicing and parsing. Because it is a ref struct, Span cannot be boxed, stored on the heap, used as a generic type argument, or passed to an async method. Memory is the heap-friendly counterpart: a regular struct that can live in fields, be passed across await boundaries, and convert to a Span via its Span property. stackalloc allocates a buffer on the stack and, in C# 7.2+, implicitly converts to Span; the buffer is automatically freed when the method returns, making it ideal for small, short-lived buffers. ArrayPool.Shared rents pre-allocated arrays to avoid repeated allocations in I/O paths, and a Span can wrap the rented array for zero-copy slicing. JIT (Just-In-Time) compilation converts IL to native code at runtime with knowledge of the actual machine, while AOT (Ahead-Of-Time) compilation produces a single-file native binary at build time, ideal for serverless workloads, CLI tools, and platforms like iOS where JIT is not allowed.

Strings are immutable in C#, so every modification creates a new allocation. This makes StringBuilder the right tool when building strings in loops or concatenating many pieces, with O(1) amortized appends. String interpolation (C# 6) embeds expressions in a string with $ and {} placeholders, with the compiler emitting a string.Format call or, in .NET 6+, a DefaultInterpolatedStringHandler for better performance. Verbatim strings (prefix @) disable escape processing and allow multi-line text, with "" for embedded quotes, and they combine with $ for interpolated verbatim strings. Raw string literals (C# 11) delimit multi-line text with three or more double quotes, allowing embedded quotes freely and using indentation rules based on the closing quote position. When the final length is known, string.Create(length, state, action) is the fastest way to format a string, since it writes directly into the backing Span without intermediate buffers.

String interning stores one copy of each distinct literal in a global pool, with string.Intern and string.IsInterned for runtime values; interned strings are reference-equal, which can be useful for memory optimization but is risky for unbounded or untrusted data. StringComparison.Ordinal compares raw code units, is culture-independent and fast, and is appropriate for internal identifiers, paths, and security checks; StringComparison.CurrentCulture uses the current culture's collation rules and suits user-visible text. Similarly, StringComparer.Ordinal is the right choice for hash-based collections of identifiers, while StringComparer.InvariantCulture applies the invariant culture's rules for cross-machine consistency. The System.Text.Encoding class converts between chars and bytes: Encoding.UTF8 is the safe default, while Encoding.Default uses the system's ANSI code page and should be avoided in cross-platform code. For null checks, string.IsNullOrEmpty covers null and empty strings, while string.IsNullOrWhiteSpace also treats whitespace-only strings as null. The Convert class uses banker's rounding on doubles and tolerates null input, while an explicit cast on a double truncates toward zero. Boxing and unboxing remain expensive in hot paths, which is why generics like List are preferred over ArrayList. File.ReadAllText returns the entire file as a single string, File.ReadAllLines returns a string[] of lines, and File.ReadLines returns a lazy IEnumerable for streaming large files.

All chapters
  1. 1Type System and Language Fundamentals
  2. 2Functions, Delegates, and Events
  3. 3Modern C# Language Features
  4. 4LINQ and Data Querying
  5. 5Asynchronous and Parallel Programming
  6. 6Memory, Performance, and Strings
  7. 7Collections, Concurrency, Resources, and Diagnostics

Drill it

Reading is not remembering. These come from the Csharp Programming deck:

Q

What is LINQ in C#?

LINQ (Language Integrated Query) is a set of features that allows you to write query expressions directly in C# to filter, sort, and transform data from collect...

Q

What is the difference between LINQ query syntax and method syntax?

Query syntax resembles SQL:var q = from x in list where x > 5 select x;Method syntax uses extension methods:var q = list.Where(x => x > 5);Both compile to the s...

Q

What does the LINQ Select method do?

Select projects each element of a sequence into a new form (a transformation/map operation).var names = people.Select(p => p.Name);It returns an IEnumerable<...

Q

What is deferred execution in LINQ?

Deferred execution means a LINQ query is not executed when defined, but only when the results are enumerated (e.g., via foreach, ToList(), or Count()). This all...