Skip to content

C# Yield Return — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about C# Yield Return. We cover key concepts, practical examples, and best practices.

You write a method that returns a list of filtered items. The method computes all items, adds them to a list, and returns the list. The caller might only need the first three items, but all items are computed anyway. yield return produces items on demand.

Wrong

public List<int> GetEvenNumbers(int max)
{
    var result = new List<int>();
    for (int i = 0; i < max; i++)
    {
        if (i % 2 == 0)
            result.Add(i);
    }
    return result;
}

Output: Returns a List<int> with all evens. If the caller only wants the first 5, the method generates all max numbers wastefully.

public IEnumerable<int> GetEvenNumbers(int max)
{
    for (int i = 0; i < max; i++)
    {
        if (i % 2 == 0)
            yield return i;
    }
}

// Usage
foreach (var n in GetEvenNumbers(100).Take(5))
{
    Console.WriteLine(n); // Only computes first 5 evens
}

Output: 0, 2, 4, 6, 8 — only 5 numbers computed. The method pauses after each yield return and resumes on the next iteration.

Prevention

  • Use yield return to create lazy sequences — items are produced on demand.
  • Use yield break to end the sequence early.
  • Use yield return for large or infinite sequences where buffering is wasteful.
  • Do not use yield return in methods that throw exceptions eagerly — the exception is deferred until iteration starts.
  • Use yield return with IAsyncEnumerable<T> for async streaming.
  • Do not combine yield return with ref or out parameters — not supported.
  • Avoid modifying the source collection during iteration — it throws InvalidOperationException.

Common Mistakes with yield return

  1. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  2. Using head and tail instead of pattern matching, causing runtime errors on empty lists
  3. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks

These mistakes appear frequently in real-world CSHARP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

How does yield return work internally?

The compiler generates a state machine class implementing IEnumerable<T> and IEnumerator<T>. The state machine tracks the current position, local variables, and the execution context. Each yield return stores the value and pauses execution.

Can I use yield return with try-catch?

Limited. yield return cannot be inside a try-catch block (except try-finally). Use yield return inside the try block of a try-finally — the finally runs when the enumerator is disposed.

What is the difference between yield return and returning a list?

yield return is lazy — items are produced one at a time on demand. Returning a List is eager — all items are produced before the method returns. Use yield return for unbounded or expensive sequences; use List for small, known-sized data.

yield return is used in DodaZIP to stream archive entries without loading the entire archive into memory. For more C#, visit DodaTech.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro