liveBook · Manning

IEnumerable

As explained in .NET in Action, Second Edition

IEnumerable is a .NET interface representing a sequence whose elements can be enumerated.

IEnumerable represents a sequence whose elements can be visited one at a time. Arrays and other .NET collections implement it, so code can accept a sequence without requiring a particular collection type. Its GetEnumerator method returns an IEnumerator, a separate object that moves through the elements. An enumerator is not an enum: an enum defines named constants. section 3.1.1 section 2.8

The generic form specifies the element type. For example, IEnumerable<string> can represent command-line argument strings, while IEnumerable<Error> can be passed to an error-handling callback. The caller depends on the sequence contract rather than whether the values came from an array or a list. section 2.8

Listing 3.9 LINQ query translated to methods
public static Lazy<IEnumerable<string>> AllFonts =
  new (() =>
    typeof(FiggleFonts)                             #1
    .GetProperties(
      BindingFlags.Public | BindingFlags.Static)
    .Select(p => p.Name));                          #2

A reflection call obtains an array of font properties. Select projects each property to its name and returns another enumerable; the LINQ query form can be translated into this method call. Creating the projected sequence does not require enumerating it immediately. section 3.1.1

Listing 3.12 Adding skip parameter to all-fonts query
app.MapGet("/",
  (int? skip, int? take) =>       #1
  AsciiArt.AllFonts.Value
    .Skip(skip ?? 0)              #2
    .Take(take ?? 100));          #3

An ASP.NET Core endpoint composes Skip and Take over the font-name sequence to page its response. Optional query parameters receive defaults before the operations are applied. This works because LINQ operators can take an enumerable and return one for the next operation. section 3.1.1

Deferred execution matters when reading a LINQ pipeline: Select can describe a result before any code asks for an enumerator. Do not confuse constructing a query with consuming its elements. section 3.1.1

For database-backed responses, distinguish IEnumerable from IAsyncEnumerable. IEnumerable supplies a synchronous enumerator; the database-service example uses IAsyncEnumerable so results can begin flowing into an ASP.NET Core response as they arrive, rather than waiting for the full result. ASP.NET Core returns an enumerable result as a JSON array. section 5.4.1

How .NET in Action, Second Edition covers it

How deep it goes
Defines GetEnumerator and explains iterator-style traversal and deferred LINQ execution, while deferring fuller treatment of deferred execution.
Examples
Uses reflected font names, paged HTTP results, command-line arguments, and database-backed book responses.
What it assumes
Assumes familiarity with C# method calls and collections, but introduces the generic element type and enumerator contract.
What you can do after
Apply it via LINQ to project and page sequences, and evaluate when an ASP.NET Core response needs asynchronous enumeration.
How it connects
Links IEnumerable to IEnumerator, LINQ extension methods, generics, and IAsyncEnumerable.

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.