C# Mastery

Iterators: Foreach, Yield Return, and Deferred Execution

1 Views Updated 5/4/2026

Mastering Iterators & Yield

When you loop over a list using foreach, you are using the Iterator Pattern. While most developers just use it, Senior Developers use the yield keyword to create memory-efficient data streams that only process one item at a time.

1. The Power of Yield Return

Normally, if a method returns a List<User>, it must first load all 10,000 users into the web server's RAM. With yield return, you create a "State Machine" that only generates the next item when requested.

// ❌ MEMORY HEAVY: Must load the entire file into RAM first
public List<string> GetLines() { ... return list; }

// ✅ MEMORY LIGHT: Streams lines one-by-one from the disk!
public IEnumerable<string> GetLinesStreamed() 
{
    foreach(var line in File.ReadLines("bigfile.txt")) 
    {
        yield return line;
    }
}

2. Deferred Execution

When you call a method with yield, no code actually runs. The code only begins executing when the human starts their foreach loop. This is the foundation of LINQ.

3. Breaking Early: Yield Break

You can use yield break; to terminate a stream prematurely based on a condition, mimicking a break inside a loop but at the producer level.

4. Interview Mastery

Q: "Can I use 'yield' inside a try-catch block?"

Architect Answer: "You CANNOT use `yield` inside a `try-catch` block, but you CAN use it inside a `try-finally` block. This is because a `yield` statement suspends execution; the compiler generates a complex state machine behind the scenes. If an exception occurred while the method was 'paused' between yields, the CLR wouldn't know how to correctly re-enter the catch block. This is a common point of frustration for juniors, but the solution is simple: perform your error-prone work outside the yield loop or wrap the calling code in the try-catch instead."

C# Mastery
1. Modern C# & Framework Fundamentals
Introduction to the .NET Ecosystem & Runtime (JIT, CLR) C# 12/13 Top-Level Statements & Global Usings Variables, Data Types, and Value vs Reference Deep Dive Mastering Nullable Reference Types & Null Safety The Magic of Strings (Interpolation, Verbatim, and Immutability)
2. Control Flow & Logical Structures
Advanced Pattern Matching (Switch Expressions) The Precision of Numbers: Checked vs Unchecked Math Iterators: Foreach, Yield Return, and Deferred Execution Defensive Programming: Guard Clauses and Exception Mastery
3. Object-Oriented Mastery
Classes vs Structs vs Records (Which to use when?) Mastering Primary Constructors & Object Initializers Interface Architectures: Default Implementations & Segregation Polymorphism vs Composition (The Architect's Dilemma) Partial Classes, Extension Methods, and Static Classes
4. Functional C# & Collections
Delegates, Func, Action, and Predicates Lambda Expressions & The Evolution of Linq Dynamic Array Management: List<T>, Dictionary, and HashSet Custom Collections & Yielding Data streams
5. Asynchronous & Parallel Programming
Async/Await Deep Dive: Task Lifecycle & Thread Safety Synchronization Context & Avoiding Deadlocks Parallel.ForEach vs PLINQ vs Tasks CancellationToken Mastery: Surgically Aborting Operations
6. Advanced Engineering & High Performance
Generics & Constraints: Building Type-Safe Libraries Reflection and Attributes: Reading Metadata at Runtime Dependency Injection Internals (ServiceCollection from scratch) High-Performance Memory: Span<T> and ReadOnlySpan<T> Garbage Collection Segments & LOH Internals Managing Unmanaged Resources: IDisposable & Finalizers Introduction to Source Generators & Interceptors C# Interview Masterclass: Architect-Level Explanations