C# tutorials > Core C# Fundamentals > Data Structures and Collections > How do you use `yield return` for custom iterators?
How do you use `yield return` for custom iterators?
The yield return statement in C# is a powerful feature that enables you to create custom iterators for collections or sequences of data without the need to implement the entire IEnumerable and IEnumerator interfaces manually. It allows you to produce a sequence of values one at a time, on demand, which can be very efficient for large datasets or complex calculations.
Basic Implementation
This example demonstrates a simple custom iterator. The GetEvenNumbers method returns an IEnumerable<int>. Instead of creating a list and returning it, we use yield return to return each even number as it's generated. The yield return statement pauses the execution of the method and returns the value. The next time an element is requested, execution resumes from where it left off.
using System;
using System.Collections.Generic;
public class NumberSequence
{
    public IEnumerable<int> GetEvenNumbers(int max)
    {
        for (int i = 0; i <= max; i++)
        {
            if (i % 2 == 0)
            {
                yield return i;
            }
        }
    }
}
public class Example
{
    public static void Main(string[] args)
    {
        NumberSequence sequence = new NumberSequence();
        foreach (int number in sequence.GetEvenNumbers(10))
        {
            Console.WriteLine(number);
        }
    }
}Concepts Behind the Snippet
The yield return statement is the core of custom iterators in C#. When the compiler encounters a yield return statement in a method, it transforms that method into a state machine. This state machine keeps track of the current state of the iteration, so the method can be resumed from the exact point it was paused.  The IEnumerable interface provides the GetEnumerator() method, which returns an IEnumerator object.  When you use yield return, the compiler automatically generates an IEnumerator implementation for you.
Real-Life Use Case Section
Imagine you're reading a very large file, line by line. Instead of loading the entire file into memory, you can use yield return to read and process each line as it's needed. This avoids memory issues and improves performance, especially for very large files.
using System;
using System.Collections.Generic;
using System.IO;
public class FileProcessor
{
    public IEnumerable<string> ReadLines(string filePath)
    {
        using (StreamReader reader = new StreamReader(filePath))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                yield return line;
            }
        }
    }
}
public class Example
{
    public static void Main(string[] args)
    {
        // Assuming you have a file named 'data.txt'
        FileProcessor processor = new FileProcessor();
        foreach (string line in processor.ReadLines("data.txt"))
        {
            Console.WriteLine(line);
        }
    }
}Best Practices
yield break to end the iteration early:  The yield break statement exits the iterator block, signaling the end of the sequence.
Interview Tip
Be prepared to explain how yield return works under the hood.  Understanding that the compiler creates a state machine is key.  Also, be ready to discuss the benefits of using yield return, such as memory efficiency and deferred execution.
When to Use Them
Use yield return when:
Memory Footprint
yield return significantly reduces the memory footprint compared to creating and returning a complete collection.  It only holds the current value and the state of the iterator in memory, rather than the entire sequence.
Alternatives
Alternatives to yield return include:List<T>: This loads all the values into memory at once.IEnumerable and IEnumerator manually: This gives you more control but requires more code.
Pros
Cons
FAQ
- 
                        What happens when I call a method that uses `yield return`?
 When you call a method that uses yield return, the method doesn't execute immediately. Instead, the compiler generates an iterator object that implements theIEnumerableinterface. The code within the method is executed only when you start iterating over the iterator object, such as with aforeachloop.
- 
                        Can I use `yield return` in a `try-catch` block?
 Yes, you can use yield returnin atry-catchblock. However, make sure to handle exceptions properly to avoid unexpected behavior. You can also use afinallyblock to ensure that resources are released, even if an exception occurs.
- 
                        What is the difference between `yield return` and `yield break`?
 yield returnis used to return a value from the iterator and pause execution, whileyield breakis used to terminate the iteration and exit the iterator block.
