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
