Skip to content

Commit 8da4d2a

Browse files
authored
Move projection SumAsync to System.Interactive.Async (#2289)
Also introduced a INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC constant that is set during reference assembly build. This behaves identically to INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES, but enables the source code to distinguish between methods hidden because they are now in System.Linq.AsyncEumerable, and methods hidden because we moved them to System.Interactive.Async
1 parent 17dcefa commit 8da4d2a

File tree

16 files changed

+1553
-32
lines changed

16 files changed

+1553
-32
lines changed

Ix.NET/Source/System.Interactive.Async.Tests/System.Interactive.Async.Tests.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
<ItemGroup>
2121
<ProjectReference Include="..\System.Interactive.Async.Providers\System.Interactive.Async.Providers.csproj" />
22-
<ProjectReference Include="..\System.Linq.Async\System.Linq.Async.csproj" />
2322
</ItemGroup>
2423

2524
<!--

Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/Sum.cs

Lines changed: 236 additions & 0 deletions
Large diffs are not rendered by default.

Ix.NET/Source/System.Interactive.Async/System.Interactive.Async.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,22 @@
7171
<DesignTime>True</DesignTime>
7272
<AutoGen>True</AutoGen>
7373
</Compile>
74+
<Compile Update="System\Linq\Operators\Sum.Generated.cs">
75+
<DependentUpon>Sum.Generated.tt</DependentUpon>
76+
<DesignTime>True</DesignTime>
77+
<AutoGen>True</AutoGen>
78+
</Compile>
7479
</ItemGroup>
7580

7681
<ItemGroup>
7782
<None Update="System\Linq\Operators\Average.Generated.tt">
7883
<LastGenOutput>Average.Generated.cs</LastGenOutput>
7984
<Generator>TextTemplatingFileGenerator</Generator>
8085
</None>
86+
<None Update="System\Linq\Operators\Sum.Generated.tt">
87+
<LastGenOutput>Sum.Generated.cs</LastGenOutput>
88+
<Generator>TextTemplatingFileGenerator</Generator>
89+
</None>
8190
</ItemGroup>
8291

8392
<ItemGroup>

Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Sum.Generated.cs

Lines changed: 1030 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
<#@ template debug="false" hostspecific="false" language="C#" #>
2+
<#@ assembly name="System.Core" #>
3+
<#@ import namespace="System.Linq" #>
4+
<#@ import namespace="System.Text" #>
5+
<#@ import namespace="System.Collections.Generic" #>
6+
<#@ output extension=".cs" #>
7+
// Licensed to the .NET Foundation under one or more agreements.
8+
// The .NET Foundation licenses this file to you under the MIT License.
9+
// See the LICENSE file in the project root for more information.
10+
11+
using System.Collections.Generic;
12+
using System.Threading;
13+
using System.Threading.Tasks;
14+
15+
namespace System.Linq
16+
{
17+
public static partial class AsyncEnumerableEx
18+
{
19+
<#
20+
var os = new[]
21+
{
22+
new { type = "int", zero = "0", @checked = true },
23+
new { type = "long", zero = "0L", @checked = true },
24+
new { type = "float", zero = "0.0f", @checked = false },
25+
new { type = "double", zero = "0.0", @checked = false },
26+
new { type = "decimal", zero = "0m", @checked = false },
27+
new { type = "int?", zero = "0", @checked = true },
28+
new { type = "long?", zero = "0L", @checked = true },
29+
new { type = "float?", zero = "0.0f", @checked = false },
30+
new { type = "double?", zero = "0.0", @checked = false },
31+
new { type = "decimal?", zero = "0m", @checked = false },
32+
};
33+
34+
foreach (var o in os)
35+
{
36+
var n = o.type.EndsWith("?") ? ".GetValueOrDefault()" : "";
37+
38+
var typeStr = o.type;
39+
if (o.type.EndsWith("?")) {
40+
typeStr = "Nullable{" + o.type.Substring(0, 1).ToUpper() + o.type.Substring(1, o.type.Length - 2) + "}";
41+
}
42+
#>
43+
/// <summary>
44+
/// Computes the sum of a sequence of <see cref="<#=typeStr#>" /> values that are obtained by invoking a transform function on each element of the input sequence.
45+
/// </summary>
46+
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
47+
/// <param name="source">A sequence of values that are used to calculate a sum.</param>
48+
/// <param name="selector">A transform function to apply to each element.</param>
49+
/// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
50+
/// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
51+
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
52+
public static ValueTask<<#=o.type#>> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, <#=o.type#>> selector, CancellationToken cancellationToken = default)
53+
{
54+
if (source == null)
55+
throw Error.ArgumentNull(nameof(source));
56+
if (selector == null)
57+
throw Error.ArgumentNull(nameof(selector));
58+
59+
return Core(source, selector, cancellationToken);
60+
61+
static async ValueTask<<#=o.type#>> Core(IAsyncEnumerable<TSource> source, Func<TSource, <#=o.type#>> selector, CancellationToken cancellationToken)
62+
{
63+
var sum = <#=o.zero#>;
64+
65+
await foreach (TSource item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
66+
{
67+
var value = selector(item);
68+
69+
<#
70+
if (o.@checked)
71+
{
72+
#>
73+
checked
74+
{
75+
sum += value<#=n#>;
76+
}
77+
<#
78+
}
79+
else
80+
{
81+
#>
82+
sum += value<#=n#>;
83+
<#
84+
}
85+
#>
86+
}
87+
88+
return sum;
89+
}
90+
}
91+
92+
/// <summary>
93+
/// Computes the sum of a sequence of <see cref="<#=typeStr#>" /> values that are obtained by invoking a transform function on each element of the input sequence.
94+
/// </summary>
95+
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
96+
/// <param name="source">A sequence of values that are used to calculate a sum.</param>
97+
/// <param name="selector">An asynchronous transform function to apply to each element.</param>
98+
/// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
99+
/// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
100+
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
101+
public static ValueTask<<#=o.type#>> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
102+
{
103+
if (source == null)
104+
throw Error.ArgumentNull(nameof(source));
105+
if (selector == null)
106+
throw Error.ArgumentNull(nameof(selector));
107+
108+
return Core(source, selector, cancellationToken);
109+
110+
static async ValueTask<<#=o.type#>> Core(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken)
111+
{
112+
var sum = <#=o.zero#>;
113+
114+
await foreach (TSource item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
115+
{
116+
var value = await selector(item).ConfigureAwait(false);
117+
118+
<#
119+
if (o.@checked)
120+
{
121+
#>
122+
checked
123+
{
124+
sum += value<#=n#>;
125+
}
126+
<#
127+
}
128+
else
129+
{
130+
#>
131+
sum += value<#=n#>;
132+
<#
133+
}
134+
#>
135+
}
136+
137+
return sum;
138+
}
139+
}
140+
141+
/// <summary>
142+
/// Computes the sum of a sequence of <see cref="<#=typeStr#>" /> values that are obtained by invoking a transform function on each element of the input sequence.
143+
/// </summary>
144+
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
145+
/// <param name="source">A sequence of values that are used to calculate a sum.</param>
146+
/// <param name="selector">An asynchronous, cancellable transform function to apply to each element.</param>
147+
/// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
148+
/// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
149+
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
150+
public static ValueTask<<#=o.type#>> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
151+
{
152+
if (source == null)
153+
throw Error.ArgumentNull(nameof(source));
154+
if (selector == null)
155+
throw Error.ArgumentNull(nameof(selector));
156+
157+
return Core(source, selector, cancellationToken);
158+
159+
static async ValueTask<<#=o.type#>> Core(IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken)
160+
{
161+
var sum = <#=o.zero#>;
162+
163+
await foreach (TSource item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
164+
{
165+
var value = await selector(item, cancellationToken).ConfigureAwait(false);
166+
167+
<#
168+
if (o.@checked)
169+
{
170+
#>
171+
checked
172+
{
173+
sum += value<#=n#>;
174+
}
175+
<#
176+
}
177+
else
178+
{
179+
#>
180+
sum += value<#=n#>;
181+
<#
182+
}
183+
#>
184+
}
185+
186+
return sum;
187+
}
188+
}
189+
<#
190+
}
191+
#>
192+
}
193+
}

Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@
3131
<!--
3232
The ref assembly defines the public API visible at compile time, so it should not include any methods for which
3333
System.Linq.AsyncEnumerable defines source-compatible replacements, because their continued availability would
34-
cause compile-time ambiguity.
34+
cause compile-time ambiguity. Similarly, methods we have relocated to System.Interactive.Async need to be
35+
hidden here.
3536
We retain the code because we continue to make these methods available in the runtime assembly (in the lib folder)
3637
to provide binary compatibility. This project builds the runtime assembly, so we need to include these methods.
3738
-->
38-
<DefineConstants>$(DefineConstants);INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES</DefineConstants>
39+
<DefineConstants>$(DefineConstants);INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES;INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC</DefineConstants>
3940
</PropertyGroup>
4041

4142
<!--

Ix.NET/Source/System.Linq.Async/System/Linq/Operators/AsAsyncEnumerable.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace System.Linq
99
public static partial class AsyncEnumerable
1010
// NB: Synchronous LINQ to Objects doesn't hide the implementation of the source either.
1111
{
12-
#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
12+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
1313
// Note: this one isn't actually in the System.Linq.AsyncEnumerable package, so we've moved it
1414
// to System.Interactive.Async because that's the home for LINQ-like implementations for
1515
// IAsyncEnumerable<T> that aren't in the runtime libraries.
@@ -24,6 +24,6 @@ public static partial class AsyncEnumerable
2424
/// <returns>An async-enumerable sequence that hides the identity of the source sequence.</returns>
2525
/// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
2626
public static IAsyncEnumerable<TSource> AsAsyncEnumerable<TSource>(this IAsyncEnumerable<TSource> source) => source;
27-
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
27+
#endif // INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
2828
}
2929
}

Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Average.Generated.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ static async ValueTask<double> Core(IAsyncEnumerable<int> source, CancellationTo
5050
}
5151
}
5252
}
53+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
5354

55+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
5456
/// <summary>
5557
/// Computes the average of an async-enumerable sequence of <see cref="int" /> values that are obtained by invoking a transform function on each element of the input sequence.
5658
/// </summary>
@@ -222,7 +224,9 @@ static async ValueTask<double> Core(IAsyncEnumerable<long> source, CancellationT
222224
}
223225
}
224226
}
227+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
225228

229+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
226230
/// <summary>
227231
/// Computes the average of an async-enumerable sequence of <see cref="long" /> values that are obtained by invoking a transform function on each element of the input sequence.
228232
/// </summary>
@@ -394,7 +398,9 @@ static async ValueTask<float> Core(IAsyncEnumerable<float> source, CancellationT
394398
}
395399
}
396400
}
401+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
397402

403+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
398404
/// <summary>
399405
/// Computes the average of an async-enumerable sequence of <see cref="float" /> values that are obtained by invoking a transform function on each element of the input sequence.
400406
/// </summary>
@@ -566,7 +572,9 @@ static async ValueTask<double> Core(IAsyncEnumerable<double> source, Cancellatio
566572
}
567573
}
568574
}
575+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
569576

577+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
570578
/// <summary>
571579
/// Computes the average of an async-enumerable sequence of <see cref="double" /> values that are obtained by invoking a transform function on each element of the input sequence.
572580
/// </summary>
@@ -738,7 +746,9 @@ static async ValueTask<decimal> Core(IAsyncEnumerable<decimal> source, Cancellat
738746
}
739747
}
740748
}
749+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
741750

751+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
742752
/// <summary>
743753
/// Computes the average of an async-enumerable sequence of <see cref="decimal" /> values that are obtained by invoking a transform function on each element of the input sequence.
744754
/// </summary>
@@ -918,7 +928,9 @@ static async ValueTask<decimal> Core(IAsyncEnumerable<TSource> source, Func<TSou
918928
return null;
919929
}
920930
}
931+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
921932

933+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
922934
/// <summary>
923935
/// Computes the average of an async-enumerable sequence of <see cref="Nullable{Int}" /> values that are obtained by invoking a transform function on each element of the input sequence.
924936
/// </summary>
@@ -1122,7 +1134,9 @@ static async ValueTask<decimal> Core(IAsyncEnumerable<TSource> source, Func<TSou
11221134
return null;
11231135
}
11241136
}
1137+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
11251138

1139+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
11261140
/// <summary>
11271141
/// Computes the average of an async-enumerable sequence of <see cref="Nullable{Long}" /> values that are obtained by invoking a transform function on each element of the input sequence.
11281142
/// </summary>
@@ -1326,7 +1340,9 @@ static async ValueTask<decimal> Core(IAsyncEnumerable<TSource> source, Func<TSou
13261340
return null;
13271341
}
13281342
}
1343+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
13291344

1345+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
13301346
/// <summary>
13311347
/// Computes the average of an async-enumerable sequence of <see cref="Nullable{Float}" /> values that are obtained by invoking a transform function on each element of the input sequence.
13321348
/// </summary>
@@ -1530,7 +1546,9 @@ static async ValueTask<decimal> Core(IAsyncEnumerable<TSource> source, Func<TSou
15301546
return null;
15311547
}
15321548
}
1549+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
15331550

1551+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
15341552
/// <summary>
15351553
/// Computes the average of an async-enumerable sequence of <see cref="Nullable{Double}" /> values that are obtained by invoking a transform function on each element of the input sequence.
15361554
/// </summary>
@@ -1734,7 +1752,9 @@ static async ValueTask<decimal> Core(IAsyncEnumerable<TSource> source, Func<TSou
17341752
return null;
17351753
}
17361754
}
1755+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
17371756

1757+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
17381758
/// <summary>
17391759
/// Computes the average of an async-enumerable sequence of <see cref="Nullable{Decimal}" /> values that are obtained by invoking a transform function on each element of the input sequence.
17401760
/// </summary>

Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Average.Generated.tt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ else
130130
#>
131131
}
132132
}
133+
#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
133134

135+
#if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC
134136
/// <summary>
135137
/// Computes the average of an async-enumerable sequence of <see cref="<#=typeStr#>" /> values that are obtained by invoking a transform function on each element of the input sequence.
136138
/// </summary>

0 commit comments

Comments
 (0)