Question
In C#, I saw this method used in an answer about exposing only part of an IList<>:
IEnumerable<object> FilteredList()
{
foreach (object item in FullList)
{
if (IsItemInPartialList(item))
yield return item;
}
}
What does the yield keyword do in this method?
I have seen yield mentioned in a few places, but I do not yet understand what it actually does. I am familiar with the word yield in the sense of one thread yielding to another, but that does not seem to apply here. How does yield return work in C#?
Short Answer
By the end of this page, you will understand that yield in C# is used to create iterators—methods that produce values one at a time instead of building and returning a whole collection immediately. You will learn how yield return works, why it enables lazy evaluation, how enumeration resumes from where it left off, and when to use it in real code.
Concept
In C#, the yield keyword is used inside a method, property, or operator to return elements of a sequence one at a time.
The most common form is:
yield return value;
When a method contains yield return, it becomes an iterator method. Instead of running all the code at once and returning a fully built collection, C# transforms the method into something that can be paused and resumed during enumeration.
That means:
- The method returns an
IEnumerable<T>orIEnumerator<T>sequence. - Each
yield returnproduces one item. - Execution pauses after returning that item.
- The next time the caller asks for another item, execution continues from the same place.
For example, this method:
IEnumerable<int> GetNumbers()
{
yield return 1;
yield return 2;
yield return 3;
}
behaves like a sequence that produces , then , then as it is iterated.
Mental Model
Think of yield return like a librarian handing you books one at a time from a shelf.
- A normal
returnis like putting all requested books into a box and handing you the whole box at once. - A
yield returnis like giving you one book, waiting until you ask again, then continuing from the exact place on the shelf where the librarian stopped.
So the method does not finish all at once. It pauses, remembers its position, and continues later.
That is the key idea behind iterators in C#:
return= give back one final result and end the methodyield return= give back one element of a sequence and pauseyield break= stop producing more elements
Syntax and Examples
The basic syntax looks like this:
IEnumerable<int> GetValues()
{
yield return 10;
yield return 20;
yield return 30;
}
You can use it with foreach:
foreach (int value in GetValues())
{
Console.WriteLine(value);
}
Output:
10
20
30
Example: filtering values
IEnumerable<int> GetEvenNumbers(List<int> numbers)
{
foreach (int number in numbers)
{
if (number % 2 == 0)
{
yield number;
}
}
}
Step by Step Execution
Consider this method:
IEnumerable<string> GetShortWords()
{
string[] words = { "cat", "elephant", "dog", "giraffe" };
foreach (string word in words)
{
if (word.Length <= 3)
{
yield return word;
}
}
}
And this code:
foreach (string word in GetShortWords())
{
Console.WriteLine(word);
}
Here is what happens step by step:
GetShortWords()is called.- The method does not immediately loop through all words and print anything.
- It returns an enumerable object that knows how to produce values later.
- The
foreachstarts iterating. - Execution enters the iterator method.
word = "cat"- length is
3 yield return word;returns
- length is
Real World Use Cases
yield is useful anywhere you want to produce a sequence gradually.
Filtering collections
Your example is a classic case: expose only items that match a rule.
IEnumerable<Order> GetOpenOrders(IEnumerable<Order> orders)
{
foreach (var order in orders)
{
if (!order.IsClosed)
yield return order;
}
}
Reading large files line by line
Instead of loading everything into memory at once, you can yield each line.
IEnumerable<string> ReadImportantLines(string path)
{
foreach (var line in File.ReadLines(path))
{
if (line.Contains("ERROR"))
yield return line;
}
}
Generating computed data
IEnumerable<int> Squares(int count)
{
( i = ; i <= count; i++)
{
i * i;
}
}
Real Codebase Usage
In real projects, yield often appears in helper methods that expose data as IEnumerable<T> without forcing immediate allocation.
Common patterns
1. Guard clauses before iteration
IEnumerable<string> GetNames(List<User> users)
{
if (users == null)
yield break;
foreach (var user in users)
{
if (!string.IsNullOrWhiteSpace(user.Name))
yield return user.Name;
}
}
This avoids errors and cleanly returns an empty sequence when input is invalid.
2. Validation and filtering
IEnumerable<Product> GetAvailableProducts(IEnumerable<Product> products)
{
foreach (var product in products)
{
if (product.Stock > 0 && product.IsActive)
yield return product;
}
}
3. Wrapping existing collections with custom rules
Common Mistakes
1. Expecting the method to run immediately
Beginners often think this code executes everything at call time:
var result = GetEvenNumbers(numbers);
Usually, the body does not fully run until you iterate:
foreach (var n in result)
{
Console.WriteLine(n);
}
2. Confusing yield return with normal return
Broken idea:
IEnumerable<int> GetNumbers()
{
return 1;
}
This is invalid because the method must return a sequence, not a single int.
Correct:
IEnumerable<int> GetNumbers()
{
yield return 1;
}
3. Assuming the result is a stored list
This may surprise you:
Comparisons
| Concept | What it does | When to use it |
|---|---|---|
return | Ends the method and returns one final result | When you already have the complete result |
yield return | Produces one item of a sequence and pauses | When returning items one at a time |
yield break | Stops an iterator early | When no more items should be produced |
yield vs building a list
| Approach | Behavior | Pros | Cons |
|---|---|---|---|
Build and return List<T> | Computes everything first |
Cheat Sheet
IEnumerable<T> MethodName()
{
yield return item1;
yield return item2;
yield break;
}
Rules
yield returnreturns one element at a time.yield breakstops the sequence.- Iterator methods usually return
IEnumerable<T>orIEnumerator<T>. - Execution is lazy: it happens during enumeration.
- Each new enumeration starts the iterator again from the beginning.
Typical pattern
IEnumerable<int> Filter(IEnumerable<int> values)
{
foreach (var value in values)
{
if (value > 0)
yield return value;
}
}
Remember
returnends the method completely.
FAQ
What does yield return mean in C#?
It means the method is returning one item of a sequence and then pausing, so it can continue later when the next item is requested.
Does yield return create a list?
No. It creates a lazy sequence. Items are usually produced only when you iterate over them.
What is the difference between return and yield return?
return sends back one final result and ends the method. yield return sends back one sequence element and pauses the method.
When does a yield method actually execute?
Usually when the returned sequence is enumerated, such as in a foreach loop.
What does yield break do in C#?
It stops the iterator immediately, producing no more items.
Is yield return efficient?
Often yes, especially for large sequences, because it avoids building a whole collection up front.
Can I use yield for filtering data?
Yes. Filtering is one of the most common uses of yield return.
Mini Project
Description
Build a small iterator method that filters a collection of names and returns only valid entries. This demonstrates how yield return can expose a clean, lazy sequence without creating a new list manually.
Goal
Create a method that lazily returns only non-empty names with at least three characters, then iterate over the results.
Requirements
- Create a C# method that returns
IEnumerable<string>. - Loop through a collection of names.
- Use
yield returnto return only valid names. - Skip
null, empty, or too-short names. - Print the filtered names with
foreach.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Array Initialization Syntaxes Explained
Learn all common C# array initialization syntaxes with examples, rules, comparisons, and mistakes beginners often make.