Understanding the yield Keyword in C#

Introduction

When working with collections in C#, sometimes we want to return items one by one instead of all at once. This is where the yield keyword becomes very useful.

The yield keyword helps us generate values lazily, meaning values are returned only when needed instead of creating the entire list in memory.

This improves performance and memory usage, especially when working with large datasets.

What is yield in C#?

In C#, the yield keyword is used to return elements from a collection one at a time.

Normally, if we return a list, we must create the whole list first.

But with yield, C# automatically creates an iterator that returns items step by step.

There are two types:

  • yield return – Returns the next value in a collection

  • yield break – Stops the iteration

Example Without Using yield

First, let’s see a normal way to return numbers.

using System;
using System.Collections.Generic;

class Program
{
    static List<int> GetNumbers()
    {
        List<int> numbers = new List<int>();

        for (int i = 1; i <= 5; i++)
        {
            numbers.Add(i);
        }

        return numbers;
    }

    static void Main()
    {
        foreach (var num in GetNumbers())
        {
            Console.WriteLine(num);
        }
    }
}

Problem

Here we must create the entire list in memory first.

If the list is very large, it consumes more memory.

Example Using yield

Now let’s use the yield keyword.

using System;
using System.Collections.Generic;

class Program
{
    static IEnumerable<int> GetNumbers()
    {
        for (int i = 1; i <= 5; i++)
        {
            yield return i;
        }
    }

    static void Main()
    {
        foreach (var num in GetNumbers())
        {
            Console.WriteLine(num);
        }
    }
}

Output

  • 1

  • 2

  • 3

  • 4

  • 5

What Happens Here?

  • The method does not create a list.

  • Each number is generated only when the loop asks for it.

  • This saves memory.

Example Using yield break

yield break is used to stop the iteration early.

using System;
using System.Collections.Generic;

class Program
{
    static IEnumerable<int> GetNumbers()
    {
        for (int i = 1; i <= 10; i++)
        {
            if (i > 5)
                yield break;

            yield return i;
        }
    }

    static void Main()
    {
        foreach (var num in GetNumbers())
        {
            Console.WriteLine(num);
        }
    }
}

Output

  • 1

  • 2

  • 3

  • 4

  • 5

The loop stops when i becomes greater than 5.

Real-World Example

Imagine a system that reads large log files.

Without yield, the program loads all logs into memory.

With yield, logs are processed one line at a time, which improves performance.

Example:

public static IEnumerable<string> GetLogs()
{
    yield return "Login Success";
    yield return "File Uploaded";
    yield return "User Logout";
}

Advantages of Using yield

  • Improves memory efficiency

  • Generates values only when needed

  • Simplifies iterator code

  • Ideal for large datasets

When to Use yield

You should use yield when:

  • Working with large collections

  • Creating custom iterators

  • Reading files or streams

  • Generating data dynamically

Important Points to Remember

  • yield works with IEnumerable or IEnumerator.

  • It cannot be used in methods with ref or out parameters.

  • It makes code cleaner and easier to read.

Conclusion

The yield keyword in C# is a powerful feature that allows developers to return data efficiently without creating full collections in memory.

It is especially useful when working with large datasets, streams, or dynamic data generation.

Understanding and using yield properly can help you write optimized and cleaner C# code.