-
Notifications
You must be signed in to change notification settings - Fork 739
/
ToEnumerable.cs
79 lines (65 loc) · 2.67 KB
/
ToEnumerable.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading.Tasks;
namespace System.Linq
{
public static partial class AsyncEnumerable
{
// REVIEW: This type of blocking is an anti-pattern. We may want to move it to System.Interactive.Async
// and remove it from System.Linq.Async API surface.
/// <summary>
/// Converts an async-enumerable sequence to an enumerable sequence.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
/// <param name="source">An async-enumerable sequence to convert to an enumerable sequence.</param>
/// <returns>The enumerable sequence containing the elements in the async-enumerable sequence.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
public static IEnumerable<TSource> ToEnumerable<TSource>(this IAsyncEnumerable<TSource> source)
{
if (source == null)
throw Error.ArgumentNull(nameof(source));
return Core(source);
static IEnumerable<TSource> Core(IAsyncEnumerable<TSource> source)
{
var e = source.GetAsyncEnumerator(default);
try
{
while (true)
{
if (!Wait(e.MoveNextAsync()))
break;
yield return e.Current;
}
}
finally
{
Wait(e.DisposeAsync());
}
}
}
// NB: ValueTask and ValueTask<T> do not have to support blocking on a call to GetResult when backed by
// an IValueTaskSource or IValueTaskSource<T> implementation. Convert to a Task or Task<T> to do so
// in case the task hasn't completed yet.
private static void Wait(ValueTask task)
{
var awaiter = task.GetAwaiter();
if (!awaiter.IsCompleted)
{
task.AsTask().GetAwaiter().GetResult();
return;
}
awaiter.GetResult();
}
private static T Wait<T>(ValueTask<T> task)
{
var awaiter = task.GetAwaiter();
if (!awaiter.IsCompleted)
{
return task.AsTask().GetAwaiter().GetResult();
}
return awaiter.GetResult();
}
}
}