liveBook · Manning

Yield

As explained in .NET in Action, Second Edition

yield return is C# iterator syntax that produces an element and suspends execution until the next element is requested.

yield return is C# iterator syntax for producing one element at a time. It lets a method expose an enumeration without first building an array or List containing every value. section 6.6.3

When xUnit requests MemberData, it obtains the member's IEnumerable and enumerates it through the test cases. Each yield return supplies the next parameter set as enumeration proceeds. section 6.6.3

Use yield return carefully when generating test data:

  • Create a fresh test object for every yielded case; reusing one board can make xUnit treat cases as duplicates and skip them. section 6.6.3
  • Prefer it when the producer does not need to materialize all values in an additional collection. section 6.6.3
  • Combine async with yield return when processing an IAsyncEnumerable requires await; use await foreach to consume the incoming asynchronous sequence. section 8.2

Generating independent theory cases

public static IEnumerable<object[]> Boards\n{\n get\n {\n var board = new ArrayBoard(4);\n board[1, 0] = 1;\n board[3, 0] = 1;\n yield return new object[] { board, false };\n\n board = new ArrayBoard(4);\n board[1, 0] = 1;\n board[1, 2] = 1;\n yield return new object[] { board, false };\n }\n}\n\nEach yielded object array represents one MemberData invocation, and each board is newly allocated before being returned. section 6.6.3

Yielding asynchronous results

public async IAsyncEnumerable<Comic> Find(string searchText)\n{\n var foundComics = FindComicsByText(searchText);\n\n await foreach (var comic in foundComics)\n {\n comic.Image = await GetComicImageAsync(comic.ImgUrl);\n yield return comic;\n }\n}\n\nThe method processes each asynchronous result, enriches it, and yields it as part of an async stream. section 8.2

Listing 6.18 Theory test using MemberData
[Theory]
[MemberData(nameof(Boards))]                           #1
public void CheckRules(IBoard board, bool isValid)     #2
{
  var solver = new Solver(board);
  Assert.Equal(isValid, solver.IsValid());
}
  
public static IEnumerable<object[]> Boards             #3
{
  get
  {
    IBoard board = new ArrayBoard(4);                  #4
    board[1, 0] = 1;
    board[3, 0] = 1;
    yield return new object[] { board, false };        #5
    board = new ArrayBoard(4);                         #6
    board[1, 0] = 1;
    board[1, 2] = 1;
    yield return new object[] { board, false };
    board = new ArrayBoard(4);                         #7
    board[1, 2] = 1;
    board[0, 3] = 1;
    yield return new object[] { board, false };
    board = new ArrayBoard(4);                         #8
    board[1, 1] = 1;
    board[2, 3] = 1;
    yield return new object[] { board, true };
  }
}

Inspect the complete MemberData example, including the theory declaration and successive yielded Sudoku boards. section 6.6.3

Listing 8.6 Operating on an IAsyncEnumerable
private IAsyncEnumerable<Comic> FindComicsByText(
  string searchText) { }                                    #1
  
private async Task<Image> GetComicImageAsync(
  string imgUrl) { }                                        #1
  
public async IAsyncEnumerable<Comic> Find(                  #2
  string searchText)
{
  var foundComics = FindComicsByText(searchText);           #3
  
  await foreach (var comic in foundComics)                  #4
  {
    comic.Image = await GetComicImageAsync(comic.ImgUrl);   #5
    yield return comic;                                     #6
  }
}

Inspect the async-stream example that consumes an IAsyncEnumerable, awaits image loading, and yields enriched comics. section 8.2

How .NET in Action, Second Edition covers it

How deep it goes
Explains one-at-a-time enumeration, collection avoidance, object-reuse pitfalls, and async-stream composition without detailing compiler-generated state machines.
Examples
Demonstrates independent Sudoku boards for theory tests and enriched Comic objects returned from asynchronous searches.
What it assumes
Assumes familiarity with C# methods, IEnumerable, xUnit theories, and asynchronous enumeration; contrasts collections with enumerated values.
What you can do after
Build it from scratch to generate test cases or stream transformed asynchronous results one element at a time.
How it connects
Connects yield return with IEnumerable, MemberData, IAsyncEnumerable, await foreach, async streams, and xUnit.

Also explained in

Compare how 10 books explain yield →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of .NET in Action, Second Edition. The section links point to the parts of the book it draws on.