You could use the LastOrDefaultAsync
operator from the System.Linq.Async package, and then convert the resulting ValueTask<T>
to a Task
by using the AsTask
extension method. For extra convenience you could combine these two operations to one extension method ToTask
:
/// <summary>
/// Retrieves a Task object that represents the completion of this IAsyncEnumerable.
/// </summary>
public static Task ToTask<T>(this IAsyncEnumerable<T> source)
{
return source.LastOrDefaultAsync().AsTask();
}
But honestly doing a loop manually is simpler and probably more efficient:
public async static Task ToTask<T>(this IAsyncEnumerable<T> source)
{
await foreach (var _ in source.ConfigureAwait(false)) { }
}
The LastOrDefaultAsync
operator will preserve in memory the last emitted element during the enumerable's lifetime, which may prevent the element from being garbage collected in a timely manner. You could prevent this from happening by including in the query the IgnoreElements
operator from the System.Interactive.Async package, but I think it becomes too much of a hassle.