Prior to C# 8 IEnumerable and yield did not play well with Task and await.
This meant that you could only foreach over items you had to either forgo async or:
- Perform all async operations at start
- Use
IEnumerable<Task<T>>rather thanIEnumerable<T>and await each result
C# 8 allows a new await foreach syntax that paired with yield return await hides this complexity.
Code
C#
await foreach (var contents in GetTextFileContentsStream("c:\\textfiles))
Console.WriteLine(contents);
async IAsyncEnumerable<string> GetTextFileContentsStream(string path)
{
foreach (var file in Directory.GetFiles(path))
yield return await File.ReadAllTextAsync(file);
}C#
foreach (var contents in await GetFileContents("c:\\textfiles"))
Console.WriteLine(contents);
async Task<IEnumerable<string>> GetFileContents(string path)
{
var allContents = new List<string>();
foreach (var file in Directory.GetFiles(path))
allContents.Add(await File.ReadAllTextAsync(file));
return allContents;
}C#
foreach (var contents in await GetFileContents("c:\\textfiles"))
Console.WriteLine(contents);
IEnumerable<Task<string>> GetFileContents(string path)
{
foreach (var file in Directory.GetFiles(path))
yield return File.ReadAllTextAsync(file);
}