Skip to content

Instantly share code, notes, and snippets.

@bradwilson
Last active January 21, 2024 16:45
Show Gist options
  • Save bradwilson/bede8678c682c5fea83cbe47fd678a12 to your computer and use it in GitHub Desktop.
Save bradwilson/bede8678c682c5fea83cbe47fd678a12 to your computer and use it in GitHub Desktop.
Enumerable/AsyncEnumerable conversions
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
internal static class EnumerableExtensions
{
public static IAsyncEnumerable<T>? ToAsyncEnumerable<T>(IEnumerable<T>? data) =>
data == null ? null : ToAsyncEnumerableImpl(data);
async static IAsyncEnumerable<T> ToAsyncEnumerableImpl<T>(IEnumerable<T> data)
{
foreach (var dataItem in data)
yield return dataItem;
}
[return: NotNullIfNotNull(nameof(data))]
public static IEnumerable<T>? ToEnumerable<T>(this IAsyncEnumerable<T>? data) =>
data == null ? null : ToEnumerableImpl(data);
static IEnumerable<T> ToEnumerableImpl<T>(IAsyncEnumerable<T> data)
{
var enumerator = data.GetAsyncEnumerator();
try
{
while (WaitForValueTask(enumerator.MoveNextAsync()))
yield return enumerator.Current;
}
finally
{
WaitForValueTask(enumerator.DisposeAsync());
}
}
static void WaitForValueTask(ValueTask valueTask)
{
var valueTaskAwaiter = valueTask.GetAwaiter();
if (valueTaskAwaiter.IsCompleted)
return;
// Let the task complete on a thread pool thread while we block the main thread
Task.Run(valueTask.AsTask).GetAwaiter().GetResult();
}
static T WaitForValueTask<T>(ValueTask<T> valueTask)
{
var valueTaskAwaiter = valueTask.GetAwaiter();
if (valueTaskAwaiter.IsCompleted)
return valueTaskAwaiter.GetResult();
// Let the task complete on a thread pool thread while we block the main thread
return Task.Run(valueTask.AsTask).GetAwaiter().GetResult();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment