C# Yield Return Statement
Tags: csharp, dotnet, programming, webdev
Published: 2023-09-17 10:51:52

---
title: C# Yield Return Statement
published: true
date: 2023-01-21 00:00:00 UTC
tags: csharp,dotnet,programming,webdev
canonical_url: https://www.milanjovanovic.tech/blog/csharp-yield-return-statement
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kxpcjzrrs184cfznhob4.png
---
In this week's newsletter I want to talk about the `yield` keyword in **C#**. I think it's a powerful **C#** feature and I wanted to highlight the benefits.

The `yield` keyword tells the compiler that the method in which it appears is an **iterator block**. An iterator block, or method, returns an `IEnumerable` as the result. And the `yield` keyword is used to return the values for the`IEnumerable`.

An interesting thing about `IEnumerable` is that it is lazily evaluated. Calling a method with an iterator block doesn't run any code. It's only when the `IEnumerable` is iterated over, or enumerated, that we get the actual values. I'll talk about this more later.

Let's see how we can start using the `yield` keyword.

## How To Use The Yield Keyword

The `yield` keyword on it's own doesn't do anything, you have to combine it with the `return` or `break` statement:

- `yield return` - provides the next value of the iterator
- `yield-break` - signals the end of iteration

In every project I worked on, there's a piece of code similar to the following. You create a list to hold the results, add elements to the list, and return the list in the end.

```csharp
var engineers = GetSoftwareEngineers();

public IEnumerable<SoftwareEngineer> GetSoftwareEngineers()
{
    var result = new List<SoftwareEngineer>();

    for(var i = 0; i < 10; i++)
    {
        result.Add(new SoftwareEngineer
        {
            Id = i
        });
    }

    return result;
}
```

You can simplify the method using the `yield return` statement, and completely remove the intermediate list required to hold the results.

```csharp
var engineers = GetSoftwareEngineers();

public IEnumerable<SoftwareEngineer> GetSoftwareEngineers()
{
    for(var i = 0; i < 10; i++)
    {
        yield return new SoftwareEngineer
        {
            Id = i
        };
    }
}
```

However, it's important to note these two implementation are fundamentally different from each other. In the first example, the entire list is populated and materialized. In the second example, the `IEnumerable` returned will not be materialized and you have to either iterate over it inside a `foreach` loop or call `ToList()`.

## Stopping Iteration With Yield Break

You can use the `yield break` statement to stop iteration and exit the iterator block. Typically you would do this when a certain condition is met, or you only want to return a specific set of values from the iterator block.

Here's an example where this would be useful:

```csharp
Console.WriteLine(string.Join(", ", TakeWhilePositive(new[] { 1, 2, -3, 4 })));
// Output: 1, 2

public IEnumerable<int> TakeWhilePositive(IEnumerable<int> numbers)
{
    foreach(int num in numbers)
    {
        if (num > 0)
        {
            yield return num;
        }
        else
        {
            yield break;
        }
    }
}
```

## Working With IAsyncEnumerable

In **C# 8** we got the `IAsyncEnumerable` type which allows us to iterate over a collection asynchronously with the `yield` statement.

For example, this can be useful when you want to call a thid-party API multiple times to fetch some data. A common situation is when you get a list of users from the database, and then have to call an external storage service to get profile picture information.

Without `IAsyncEnumerable` you would have to do something like this:

```csharp
public async Task<IEnumerable<User>> GetUsersAsync()
{
    var users = await GetUsersFromDbAsync();

    foreach(var user in users)
    {
        user.ProfileImage = await GetProfileImageAsync(user.Id);
    }

    return users;
}

// And you would call the method like this.
var users = await GetUsersAsync();

foreach(var user in users)
{
    Console.WriteLine(user);
}
```

Now, consider this same example with the use of `IAsyncEnumerable`:

```csharp
public async IAsyncEnumerable<User> GetUsersAsync()
{
    var users = await GetUsersFromDbAsync();

    foreach(var user in users)
    {
        user.ProfileImage = await GetProfileImageAsync(user.Id);

        yield return user;
    }
}

// And you would call the method like this.
await foreach(var user in GetUsersAsync())
{
    Console.WriteLine(user);
}
```

The second implementation will iterate over the users returned from the database when they are yielded by the `IAsyncEnumerable`.

## When Should I Use Yield?

I've found a few interesting practical applications for the `yield` keyword. One example is when implementing Domain-Driven Design value objects.

Value objects need to support structural equality. They need to implement a method that returns all of the equality components. Here's an example of that using the `yield return` statement:

```csharp
public class Address
{
    public string City { get; init; }

    public string Street { get; init; }

    public string Zip { get; init; }

    public string Country { get; init; }

    public IEnumerable<object> GetEqualityComponents()
    {
        yield return City;
        yield return Street;
        yield return Zip;
        yield return Country;
    }
}
```

* * *

**P.S. Whenever you're ready, there are 2 ways I can help you:**

1. [**Pragmatic Clean Architecture:**](https://www.milanjovanovic.tech/pragmatic-clean-architecture?utm_source=dev.to&utm_medium=website&utm_campaign=cross-posting) This comprehensive course will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture. [**Join 950+ students here.**](https://www.milanjovanovic.tech/pragmatic-clean-architecture?utm_source=dev.to&utm_medium=website&utm_campaign=cross-posting)

2. [**Patreon Community:**](https://www.patreon.com/milanjovanovic) Think like a senior software engineer with **access to the source code** I use in my YouTube videos and **exclusive discounts** for my courses. [**Join 820+ engineers here.**](https://www.patreon.com/milanjovanovic)