Browse Source

Handle clashes in `System.Interactive.Async` with `System.Linq.Asyncenumerable` (#2280)

Ian Griffiths 1 week ago
parent
commit
672f8322fa
25 changed files with 1474 additions and 114 deletions
  1. 14 3
      Ix.NET/Documentation/adr/0002-System-Linq-Async-In-Net10.md
  2. 1 0
      Ix.NET/Source/ApiCompare/ApiCompare.csproj
  3. 4 0
      Ix.NET/Source/AsyncQueryableGenerator.t4
  4. 1 0
      Ix.NET/Source/Benchmarks.System.Interactive/Benchmarks.System.Interactive.csproj
  5. 1 0
      Ix.NET/Source/FasterLinq/FasterLinq.csproj
  6. 10 2
      Ix.NET/Source/Ix.NET.sln
  7. 1 0
      Ix.NET/Source/Playground/Playground.csproj
  8. 686 0
      Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.cs
  9. 76 0
      Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/MaxByWithTies.cs
  10. 76 0
      Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/MinByWithTies.cs
  11. 24 0
      Ix.NET/Source/System.Interactive.Async/System.Interactive.Async.csproj
  12. 6 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Distinct.cs
  13. 2 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Max.cs
  14. 3 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/MaxBy.cs
  15. 169 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/MaxByWithTies.cs
  16. 2 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Min.cs
  17. 1 105
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/MinBy.cs
  18. 276 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/MinByWithTies.cs
  19. 1 1
      Ix.NET/Source/System.Interactive.Providers/System.Interactive.Providers.csproj
  20. 1 1
      Ix.NET/Source/System.Interactive/System.Interactive.csproj
  21. 1 1
      Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs
  22. 1 1
      Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj
  23. 30 0
      Ix.NET/Source/Tests.System.Interactive.ApiApprovals/Api/ApiApprovalTests.SystemInteractiveAsync.verified.cs
  24. 43 0
      Ix.NET/Source/Tests.System.Interactive.ApiApprovals/Api/ApiApprovalTests.SystemInteractiveAsyncProviders.verified.cs
  25. 44 0
      Ix.NET/Source/refs/System.Interactive.Async/System.Interactive.Async.csproj

+ 14 - 3
Ix.NET/Documentation/adr/0002-System-Linq-Async-In-Net10.md

@@ -32,12 +32,15 @@ There are also a couple of cases where functionality simply has not been reprodu
 
 `System.Linq.Async` also defined some interfaces that are not replicated in `System.Linq.AsyncEnumerable`. `System.Linq.Async` defined `IAsyncGrouping` to act as the return type for `GroupBy`. `System.Linq.AsyncEnumerable` just uses `IAsyncEnumerable<IGrouping<TKey, TElement>>`, which is not quite the same: this enables asynchronous iteration of the sequence of groups, but each invidual group's contents are not asynchronously enumerable. `IAsyncGrouping` enabled asynchronous enumeration of both. In practice, `System.Linq.Async` did not exploit this: it fully enumerated the whole source list to split items into groups before returning the first group, so although it compelled you to enumerate at both levels (e.g., with nested `await foreach` loops), in reality only the outer level was asynchronous in practice. So this interface added complication without real benefits. There is also `IAsyncIListProvider<T>`, an interface that arguably should not have been public in the first place, serving only to enable some internal optimizations. (Apparently it was public in `System.Linq.Async` because it is also used in other parts of Ix.NET.) 
 
+A further complication is that some methods in `System.Interactive.Async` clash with methods in `System.Linq.AsyncEnumerable`. For example, `MaxByAsync` and `MinByAsync`. Originally `MinBy` and `MaxBy` were unique to Rx.NET and Ix.NET. But .NET 6.0 added operators with these names to LINQ to Objects. Confusingly, they were slightly different: the Rx.NET and Ix.NET versions recognize that there might not be a single minimum or maximum value, and thus provide a collection of all the entries that are at the maximum value, but the .NET runtime class library versions just pick one arbitrary winner. So at this point, `System.Interactive` renamed its versions to `MinByWithTies` and `MaxByWithTies`. Unfortunately that same change wasn't made in `System.Interactive.Async`, so we now have the same situation with `System.Linq.AsyncEnumerable`: the .NET runtime class libraries now define `MinByAsync` and `MaxByAsync` extension methods for `IAsyncEnumerable<T>`, and these take the same arguments as the ones in `System.Interactive.Async`, but have a different return type, and have different behaviour!
+
+
 ## Decision
 
-The next `System.Linq.Async` release will:
+The next Ix.NET release will:
 
-1. add a reference to `System.Linq.AsyncEnumerable` and `System.Interactive.Async`
-2. remove from publicly visible API (ref assemblies) all `IAsyncEnumerable<T>` extension methods for which direct replacements exist
+1. add a reference to `System.Linq.AsyncEnumerable` and `System.Interactive.Async` in `System.Linq.Async`
+2. remove from `System.Linq.Async`'s and `System.Interactive.Async`'s publicly visible API (ref assemblies) all `IAsyncEnumerable<T>` extension methods for which direct replacements exist (adding `MinByWithTiesAsync` and `MaxByWithTiesAsync` for the case where the new .NET runtime library methods actually have slightly different functionality)
 3. add [Obsolete] attribute for members of `AsyncEnumerable` for which `System.Linq.AsyncEnumerable` offers replacements that require code changes to use (e.g., `WhereAwait`, which is replaced by an overload of `Where`)
 4. `AsyncEnumerable` methods that are a bad idea and that should probably have never existing (the ones that do sync over async, e.g. `ToEnumerable`) are marked as `Obsolete` and will not be replaced; note that although `ToObservable` has issues that meant the .NET team decided not to replicate it, the main issue is that it embeds opinions, and not that there's anything fundamentally broken about it, so we do not include `ToObservable` in this category
 5. remaining methods of `AsyncEnumerable` (where `System.Linq.AsyncEnumerable` offers no equivalent) are removed from the publicly visible API of `System.Linq.Async`, with identical replacements being defined by `AsyncEnumerableEx` in `System.Interactive
@@ -60,6 +63,14 @@ In summary, each of the features previously provided by `System.Linq.Async` will
 * Method hidden in `ref` assembly, available in `System.Interactive.Async`
 * Method visible but marked as `Obsolete`, with new but slightly different equivalent available in `System.Linq.AsyncEnumerable`
 
+### TFMs
+
+We want to keep the TFMs for all Ix.NET packages exactly the same in this version, because the only reason for Ix.NET v7 to exist is to deal with the new existence of `System.Linq.AsyncEnumerable`.
+
+There is one issue with this. If a project has a `net6.0` target and tries to use `System.Linq.AsyncEnumerable`, it produces a build warning, saying that it's not supported on that runtime. Although we don't like having this build warning, we are currently intending not to do anything about it, because we believe that messing with the TFMs is likely to have unintended consequences.
+
+If it turns out that this does cause problems, we'll revisit this and do a new release.
+
 ## Consequences
 
 Binary compatibility is maintained: any code that was built against `System.Linq.Async` v6 but which finds itself running against v7 at runtime should continue to work exactly as before.

+ 1 - 0
Ix.NET/Source/ApiCompare/ApiCompare.csproj

@@ -3,6 +3,7 @@
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net8.0</TargetFramework>
+    <IsPackable>false</IsPackable>
   </PropertyGroup>
 
   <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">

+ 4 - 0
Ix.NET/Source/AsyncQueryableGenerator.t4

@@ -283,6 +283,10 @@ foreach (var m in asyncEnumerableType.GetMethods()
                 cast = "(" + toQuoted(m.ReturnType, null, 0) + ")";
             }
         }
+        else
+        {
+            continue; // this skips ToObservable, which we can't represent in a query
+        }
     }
 
     var n = 0;

+ 1 - 0
Ix.NET/Source/Benchmarks.System.Interactive/Benchmarks.System.Interactive.csproj

@@ -3,6 +3,7 @@
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net8.0</TargetFramework>
+    <IsPackable>false</IsPackable>
     <Optimize>true</Optimize>
     <Configurations>Current Sources;Ix.net 3.1.1;Ix.net 3.2</Configurations>
   </PropertyGroup>

+ 1 - 0
Ix.NET/Source/FasterLinq/FasterLinq.csproj

@@ -3,6 +3,7 @@
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net8.0</TargetFramework>
+    <IsPackable>false</IsPackable>
 
     <NoWarn>$(NoWarn);IDE0007;IDE0034;IDE0040;IDE0063;IDE0090;IDE1006</NoWarn>
   </PropertyGroup>

+ 10 - 2
Ix.NET/Source/Ix.NET.sln

@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.2.32131.331
+# Visual Studio Version 18
+VisualStudioVersion = 18.0.11205.157 d18.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{87534290-A7A6-47A4-9A3A-D0D21A9AD1D4}"
 	ProjectSection(SolutionItems) = preProject
@@ -11,6 +11,7 @@ EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B733D97A-F1ED-4FC3-BF8E-9AC47A89DE96}"
 	ProjectSection(SolutionItems) = preProject
 		..\..\.editorconfig = ..\..\.editorconfig
+		AsyncQueryableGenerator.t4 = AsyncQueryableGenerator.t4
 		..\..\azure-pipelines.ix.yml = ..\..\azure-pipelines.ix.yml
 		CodeCoverage.runsettings = CodeCoverage.runsettings
 		Directory.build.props = Directory.build.props
@@ -76,6 +77,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Linq.Async.SourceGen
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.System.Interactive.ApiApprovals", "Tests.System.Interactive.ApiApprovals\Tests.System.Interactive.ApiApprovals.csproj", "{CD146918-6465-4D5B-B6B7-3F9803095EBD}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Interactive.Async", "refs\System.Interactive.Async\System.Interactive.Async.csproj", "{74613134-0799-190D-7023-EC9A28B3A1F2}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -156,6 +159,10 @@ Global
 		{CD146918-6465-4D5B-B6B7-3F9803095EBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{CD146918-6465-4D5B-B6B7-3F9803095EBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{CD146918-6465-4D5B-B6B7-3F9803095EBD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{74613134-0799-190D-7023-EC9A28B3A1F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{74613134-0799-190D-7023-EC9A28B3A1F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{74613134-0799-190D-7023-EC9A28B3A1F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{74613134-0799-190D-7023-EC9A28B3A1F2}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -180,6 +187,7 @@ Global
 		{1754B36C-D0DB-4E5D-8C30-1F116046DC0F} = {A3D72E6E-4ADA-42E0-8B2A-055B1F244281}
 		{5C26D649-5ED4-49EE-AFBD-8FA8F12C4AE4} = {80EFE3A1-1414-42EA-949B-1B5370A1B2EA}
 		{CD146918-6465-4D5B-B6B7-3F9803095EBD} = {87534290-A7A6-47A4-9A3A-D0D21A9AD1D4}
+		{74613134-0799-190D-7023-EC9A28B3A1F2} = {A3D72E6E-4ADA-42E0-8B2A-055B1F244281}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {AF70B0C6-C9D9-43B1-9BE4-08720EC1B7B7}

+ 1 - 0
Ix.NET/Source/Playground/Playground.csproj

@@ -3,6 +3,7 @@
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net8.0</TargetFramework>
+    <IsPackable>false</IsPackable>
   </PropertyGroup>
 
   <ItemGroup>

+ 686 - 0
Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.cs

@@ -30,6 +30,500 @@ namespace System.Linq
             return first.Provider.CreateQuery<TSource>(Expression.Call(Amb__TSource__2__0(typeof(TSource)), first.Expression, GetSourceExpression(second)));
         }
 
+        private static MethodInfo? s_AsAsyncEnumerable__TSource__1__0;
+        
+        private static MethodInfo AsAsyncEnumerable__TSource__1__0(Type TSource) =>
+            (s_AsAsyncEnumerable__TSource__1__0 ??
+            (s_AsAsyncEnumerable__TSource__1__0 = new Func<IAsyncQueryable<object>, IAsyncQueryable<object>>(AsAsyncEnumerable<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static IAsyncQueryable<TSource> AsAsyncEnumerable<TSource>(this IAsyncQueryable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Provider.CreateQuery<TSource>(Expression.Call(AsAsyncEnumerable__TSource__1__0(typeof(TSource)), source.Expression));
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__0;
+        
+        private static MethodInfo AverageAsync__TSource__3__0(Type TSource) =>
+            (s_AverageAsync__TSource__3__0 ??
+            (s_AverageAsync__TSource__3__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<decimal?>>>, CancellationToken, ValueTask<decimal?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<decimal?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<decimal?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<decimal?>(Expression.Call(AverageAsync__TSource__3__0(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__1;
+        
+        private static MethodInfo AverageAsync__TSource__3__1(Type TSource) =>
+            (s_AverageAsync__TSource__3__1 ??
+            (s_AverageAsync__TSource__3__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<decimal>>>, CancellationToken, ValueTask<decimal>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<decimal> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<decimal>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<decimal>(Expression.Call(AverageAsync__TSource__3__1(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__2;
+        
+        private static MethodInfo AverageAsync__TSource__3__2(Type TSource) =>
+            (s_AverageAsync__TSource__3__2 ??
+            (s_AverageAsync__TSource__3__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<double?>>>, CancellationToken, ValueTask<double?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<double?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double?>(Expression.Call(AverageAsync__TSource__3__2(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__3;
+        
+        private static MethodInfo AverageAsync__TSource__3__3(Type TSource) =>
+            (s_AverageAsync__TSource__3__3 ??
+            (s_AverageAsync__TSource__3__3 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<double>>>, CancellationToken, ValueTask<double>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<double>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double>(Expression.Call(AverageAsync__TSource__3__3(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__4;
+        
+        private static MethodInfo AverageAsync__TSource__3__4(Type TSource) =>
+            (s_AverageAsync__TSource__3__4 ??
+            (s_AverageAsync__TSource__3__4 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<float?>>>, CancellationToken, ValueTask<float?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<float?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<float?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<float?>(Expression.Call(AverageAsync__TSource__3__4(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__5;
+        
+        private static MethodInfo AverageAsync__TSource__3__5(Type TSource) =>
+            (s_AverageAsync__TSource__3__5 ??
+            (s_AverageAsync__TSource__3__5 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<float>>>, CancellationToken, ValueTask<float>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<float> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<float>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<float>(Expression.Call(AverageAsync__TSource__3__5(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__6;
+        
+        private static MethodInfo AverageAsync__TSource__3__6(Type TSource) =>
+            (s_AverageAsync__TSource__3__6 ??
+            (s_AverageAsync__TSource__3__6 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<int?>>>, CancellationToken, ValueTask<double?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<int?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double?>(Expression.Call(AverageAsync__TSource__3__6(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__7;
+        
+        private static MethodInfo AverageAsync__TSource__3__7(Type TSource) =>
+            (s_AverageAsync__TSource__3__7 ??
+            (s_AverageAsync__TSource__3__7 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<int>>>, CancellationToken, ValueTask<double>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<int>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double>(Expression.Call(AverageAsync__TSource__3__7(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__8;
+        
+        private static MethodInfo AverageAsync__TSource__3__8(Type TSource) =>
+            (s_AverageAsync__TSource__3__8 ??
+            (s_AverageAsync__TSource__3__8 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<long?>>>, CancellationToken, ValueTask<double?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<long?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double?>(Expression.Call(AverageAsync__TSource__3__8(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__9;
+        
+        private static MethodInfo AverageAsync__TSource__3__9(Type TSource) =>
+            (s_AverageAsync__TSource__3__9 ??
+            (s_AverageAsync__TSource__3__9 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<long>>>, CancellationToken, ValueTask<double>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<long>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double>(Expression.Call(AverageAsync__TSource__3__9(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__10;
+        
+        private static MethodInfo AverageAsync__TSource__3__10(Type TSource) =>
+            (s_AverageAsync__TSource__3__10 ??
+            (s_AverageAsync__TSource__3__10 = new Func<IAsyncQueryable<object>, Expression<Func<object, decimal?>>, CancellationToken, ValueTask<decimal?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<decimal?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, decimal?>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<decimal?>(Expression.Call(AverageAsync__TSource__3__10(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__11;
+        
+        private static MethodInfo AverageAsync__TSource__3__11(Type TSource) =>
+            (s_AverageAsync__TSource__3__11 ??
+            (s_AverageAsync__TSource__3__11 = new Func<IAsyncQueryable<object>, Expression<Func<object, decimal>>, CancellationToken, ValueTask<decimal>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<decimal> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, decimal>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<decimal>(Expression.Call(AverageAsync__TSource__3__11(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__12;
+        
+        private static MethodInfo AverageAsync__TSource__3__12(Type TSource) =>
+            (s_AverageAsync__TSource__3__12 ??
+            (s_AverageAsync__TSource__3__12 = new Func<IAsyncQueryable<object>, Expression<Func<object, double?>>, CancellationToken, ValueTask<double?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, double?>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double?>(Expression.Call(AverageAsync__TSource__3__12(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__13;
+        
+        private static MethodInfo AverageAsync__TSource__3__13(Type TSource) =>
+            (s_AverageAsync__TSource__3__13 ??
+            (s_AverageAsync__TSource__3__13 = new Func<IAsyncQueryable<object>, Expression<Func<object, double>>, CancellationToken, ValueTask<double>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, double>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double>(Expression.Call(AverageAsync__TSource__3__13(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__14;
+        
+        private static MethodInfo AverageAsync__TSource__3__14(Type TSource) =>
+            (s_AverageAsync__TSource__3__14 ??
+            (s_AverageAsync__TSource__3__14 = new Func<IAsyncQueryable<object>, Expression<Func<object, float?>>, CancellationToken, ValueTask<float?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<float?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, float?>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<float?>(Expression.Call(AverageAsync__TSource__3__14(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__15;
+        
+        private static MethodInfo AverageAsync__TSource__3__15(Type TSource) =>
+            (s_AverageAsync__TSource__3__15 ??
+            (s_AverageAsync__TSource__3__15 = new Func<IAsyncQueryable<object>, Expression<Func<object, float>>, CancellationToken, ValueTask<float>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<float> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, float>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<float>(Expression.Call(AverageAsync__TSource__3__15(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__16;
+        
+        private static MethodInfo AverageAsync__TSource__3__16(Type TSource) =>
+            (s_AverageAsync__TSource__3__16 ??
+            (s_AverageAsync__TSource__3__16 = new Func<IAsyncQueryable<object>, Expression<Func<object, int?>>, CancellationToken, ValueTask<double?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, int?>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double?>(Expression.Call(AverageAsync__TSource__3__16(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__17;
+        
+        private static MethodInfo AverageAsync__TSource__3__17(Type TSource) =>
+            (s_AverageAsync__TSource__3__17 ??
+            (s_AverageAsync__TSource__3__17 = new Func<IAsyncQueryable<object>, Expression<Func<object, int>>, CancellationToken, ValueTask<double>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, int>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double>(Expression.Call(AverageAsync__TSource__3__17(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__18;
+        
+        private static MethodInfo AverageAsync__TSource__3__18(Type TSource) =>
+            (s_AverageAsync__TSource__3__18 ??
+            (s_AverageAsync__TSource__3__18 = new Func<IAsyncQueryable<object>, Expression<Func<object, long?>>, CancellationToken, ValueTask<double?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, long?>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double?>(Expression.Call(AverageAsync__TSource__3__18(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__19;
+        
+        private static MethodInfo AverageAsync__TSource__3__19(Type TSource) =>
+            (s_AverageAsync__TSource__3__19 ??
+            (s_AverageAsync__TSource__3__19 = new Func<IAsyncQueryable<object>, Expression<Func<object, long>>, CancellationToken, ValueTask<double>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, long>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double>(Expression.Call(AverageAsync__TSource__3__19(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__20;
+        
+        private static MethodInfo AverageAsync__TSource__3__20(Type TSource) =>
+            (s_AverageAsync__TSource__3__20 ??
+            (s_AverageAsync__TSource__3__20 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<decimal?>>>, CancellationToken, ValueTask<decimal?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<decimal?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<decimal?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<decimal?>(Expression.Call(AverageAsync__TSource__3__20(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__21;
+        
+        private static MethodInfo AverageAsync__TSource__3__21(Type TSource) =>
+            (s_AverageAsync__TSource__3__21 ??
+            (s_AverageAsync__TSource__3__21 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<decimal>>>, CancellationToken, ValueTask<decimal>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<decimal> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<decimal>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<decimal>(Expression.Call(AverageAsync__TSource__3__21(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__22;
+        
+        private static MethodInfo AverageAsync__TSource__3__22(Type TSource) =>
+            (s_AverageAsync__TSource__3__22 ??
+            (s_AverageAsync__TSource__3__22 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<double?>>>, CancellationToken, ValueTask<double?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<double?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double?>(Expression.Call(AverageAsync__TSource__3__22(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__23;
+        
+        private static MethodInfo AverageAsync__TSource__3__23(Type TSource) =>
+            (s_AverageAsync__TSource__3__23 ??
+            (s_AverageAsync__TSource__3__23 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<double>>>, CancellationToken, ValueTask<double>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<double>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double>(Expression.Call(AverageAsync__TSource__3__23(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__24;
+        
+        private static MethodInfo AverageAsync__TSource__3__24(Type TSource) =>
+            (s_AverageAsync__TSource__3__24 ??
+            (s_AverageAsync__TSource__3__24 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<float?>>>, CancellationToken, ValueTask<float?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<float?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<float?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<float?>(Expression.Call(AverageAsync__TSource__3__24(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__25;
+        
+        private static MethodInfo AverageAsync__TSource__3__25(Type TSource) =>
+            (s_AverageAsync__TSource__3__25 ??
+            (s_AverageAsync__TSource__3__25 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<float>>>, CancellationToken, ValueTask<float>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<float> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<float>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<float>(Expression.Call(AverageAsync__TSource__3__25(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__26;
+        
+        private static MethodInfo AverageAsync__TSource__3__26(Type TSource) =>
+            (s_AverageAsync__TSource__3__26 ??
+            (s_AverageAsync__TSource__3__26 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<int?>>>, CancellationToken, ValueTask<double?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<int?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double?>(Expression.Call(AverageAsync__TSource__3__26(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__27;
+        
+        private static MethodInfo AverageAsync__TSource__3__27(Type TSource) =>
+            (s_AverageAsync__TSource__3__27 ??
+            (s_AverageAsync__TSource__3__27 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<int>>>, CancellationToken, ValueTask<double>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<int>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double>(Expression.Call(AverageAsync__TSource__3__27(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__28;
+        
+        private static MethodInfo AverageAsync__TSource__3__28(Type TSource) =>
+            (s_AverageAsync__TSource__3__28 ??
+            (s_AverageAsync__TSource__3__28 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<long?>>>, CancellationToken, ValueTask<double?>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double?> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<long?>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double?>(Expression.Call(AverageAsync__TSource__3__28(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_AverageAsync__TSource__3__29;
+        
+        private static MethodInfo AverageAsync__TSource__3__29(Type TSource) =>
+            (s_AverageAsync__TSource__3__29 ??
+            (s_AverageAsync__TSource__3__29 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<long>>>, CancellationToken, ValueTask<double>>(AverageAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
+
+        public static ValueTask<double> AverageAsync<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<long>>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Provider.ExecuteAsync<double>(Expression.Call(AverageAsync__TSource__3__29(typeof(TSource)), source.Expression, selector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
         private static MethodInfo? s_Buffer__TSource__2__0;
         
         private static MethodInfo Buffer__TSource__2__0(Type TSource) =>
@@ -806,6 +1300,102 @@ namespace System.Linq
             return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MaxByAsync__TSource_TKey__4__2(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(comparer, typeof(IComparer<TKey>)), Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
         }
 
+        private static MethodInfo? s_MaxByWithTiesAsync__TSource_TKey__3__0;
+        
+        private static MethodInfo MaxByWithTiesAsync__TSource_TKey__3__0(Type TSource, Type TKey) =>
+            (s_MaxByWithTiesAsync__TSource_TKey__3__0 ??
+            (s_MaxByWithTiesAsync__TSource_TKey__3__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, CancellationToken, ValueTask<IList<object>>>(MaxByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<TKey>>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MaxByWithTiesAsync__TSource_TKey__3__0(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MaxByWithTiesAsync__TSource_TKey__3__1;
+        
+        private static MethodInfo MaxByWithTiesAsync__TSource_TKey__3__1(Type TSource, Type TKey) =>
+            (s_MaxByWithTiesAsync__TSource_TKey__3__1 ??
+            (s_MaxByWithTiesAsync__TSource_TKey__3__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, CancellationToken, ValueTask<IList<object>>>(MaxByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MaxByWithTiesAsync__TSource_TKey__3__1(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MaxByWithTiesAsync__TSource_TKey__3__2;
+        
+        private static MethodInfo MaxByWithTiesAsync__TSource_TKey__3__2(Type TSource, Type TKey) =>
+            (s_MaxByWithTiesAsync__TSource_TKey__3__2 ??
+            (s_MaxByWithTiesAsync__TSource_TKey__3__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, CancellationToken, ValueTask<IList<object>>>(MaxByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<TKey>>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MaxByWithTiesAsync__TSource_TKey__3__2(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MaxByWithTiesAsync__TSource_TKey__4__0;
+        
+        private static MethodInfo MaxByWithTiesAsync__TSource_TKey__4__0(Type TSource, Type TKey) =>
+            (s_MaxByWithTiesAsync__TSource_TKey__4__0 ??
+            (s_MaxByWithTiesAsync__TSource_TKey__4__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MaxByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<TKey>>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MaxByWithTiesAsync__TSource_TKey__4__0(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(comparer, typeof(IComparer<TKey>)), Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MaxByWithTiesAsync__TSource_TKey__4__1;
+        
+        private static MethodInfo MaxByWithTiesAsync__TSource_TKey__4__1(Type TSource, Type TKey) =>
+            (s_MaxByWithTiesAsync__TSource_TKey__4__1 ??
+            (s_MaxByWithTiesAsync__TSource_TKey__4__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MaxByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MaxByWithTiesAsync__TSource_TKey__4__1(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(comparer, typeof(IComparer<TKey>)), Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MaxByWithTiesAsync__TSource_TKey__4__2;
+        
+        private static MethodInfo MaxByWithTiesAsync__TSource_TKey__4__2(Type TSource, Type TKey) =>
+            (s_MaxByWithTiesAsync__TSource_TKey__4__2 ??
+            (s_MaxByWithTiesAsync__TSource_TKey__4__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MaxByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<TKey>>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MaxByWithTiesAsync__TSource_TKey__4__2(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(comparer, typeof(IComparer<TKey>)), Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
         private static MethodInfo? s_Merge__TSource__1__0;
         
         private static MethodInfo Merge__TSource__1__0(Type TSource) =>
@@ -930,6 +1520,102 @@ namespace System.Linq
             return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MinByAsync__TSource_TKey__4__2(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(comparer, typeof(IComparer<TKey>)), Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
         }
 
+        private static MethodInfo? s_MinByWithTiesAsync__TSource_TKey__3__0;
+        
+        private static MethodInfo MinByWithTiesAsync__TSource_TKey__3__0(Type TSource, Type TKey) =>
+            (s_MinByWithTiesAsync__TSource_TKey__3__0 ??
+            (s_MinByWithTiesAsync__TSource_TKey__3__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, CancellationToken, ValueTask<IList<object>>>(MinByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<TKey>>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MinByWithTiesAsync__TSource_TKey__3__0(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MinByWithTiesAsync__TSource_TKey__3__1;
+        
+        private static MethodInfo MinByWithTiesAsync__TSource_TKey__3__1(Type TSource, Type TKey) =>
+            (s_MinByWithTiesAsync__TSource_TKey__3__1 ??
+            (s_MinByWithTiesAsync__TSource_TKey__3__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, CancellationToken, ValueTask<IList<object>>>(MinByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MinByWithTiesAsync__TSource_TKey__3__1(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MinByWithTiesAsync__TSource_TKey__3__2;
+        
+        private static MethodInfo MinByWithTiesAsync__TSource_TKey__3__2(Type TSource, Type TKey) =>
+            (s_MinByWithTiesAsync__TSource_TKey__3__2 ??
+            (s_MinByWithTiesAsync__TSource_TKey__3__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, CancellationToken, ValueTask<IList<object>>>(MinByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<TKey>>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MinByWithTiesAsync__TSource_TKey__3__2(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MinByWithTiesAsync__TSource_TKey__4__0;
+        
+        private static MethodInfo MinByWithTiesAsync__TSource_TKey__4__0(Type TSource, Type TKey) =>
+            (s_MinByWithTiesAsync__TSource_TKey__4__0 ??
+            (s_MinByWithTiesAsync__TSource_TKey__4__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MinByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<TKey>>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MinByWithTiesAsync__TSource_TKey__4__0(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(comparer, typeof(IComparer<TKey>)), Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MinByWithTiesAsync__TSource_TKey__4__1;
+        
+        private static MethodInfo MinByWithTiesAsync__TSource_TKey__4__1(Type TSource, Type TKey) =>
+            (s_MinByWithTiesAsync__TSource_TKey__4__1 ??
+            (s_MinByWithTiesAsync__TSource_TKey__4__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MinByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MinByWithTiesAsync__TSource_TKey__4__1(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(comparer, typeof(IComparer<TKey>)), Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
+        private static MethodInfo? s_MinByWithTiesAsync__TSource_TKey__4__2;
+        
+        private static MethodInfo MinByWithTiesAsync__TSource_TKey__4__2(Type TSource, Type TKey) =>
+            (s_MinByWithTiesAsync__TSource_TKey__4__2 ??
+            (s_MinByWithTiesAsync__TSource_TKey__4__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MinByWithTiesAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
+
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, ValueTask<TKey>>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Provider.ExecuteAsync<IList<TSource>>(Expression.Call(MinByWithTiesAsync__TSource_TKey__4__2(typeof(TSource), typeof(TKey)), source.Expression, keySelector, Expression.Constant(comparer, typeof(IComparer<TKey>)), Expression.Constant(cancellationToken, typeof(CancellationToken))), cancellationToken);
+        }
+
         private static MethodInfo? s_OnErrorResumeNext__TSource__2__0;
         
         private static MethodInfo OnErrorResumeNext__TSource__2__0(Type TSource) =>

+ 76 - 0
Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/MaxByWithTies.cs

@@ -0,0 +1,76 @@
+// 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Tests
+{
+    public class MaxByWithTies : AsyncEnumerableExTests
+    {
+        [Fact]
+        public async Task MaxByWithTies_Null()
+        {
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxByWithTiesAsync(default(IAsyncEnumerable<int>), x => x).AsTask());
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxByWithTiesAsync(Return42, default(Func<int, int>)).AsTask());
+
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxByWithTiesAsync(default(IAsyncEnumerable<int>), x => x, Comparer<int>.Default).AsTask());
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxByWithTiesAsync(Return42, default(Func<int, int>), Comparer<int>.Default).AsTask());
+
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxByWithTiesAsync(default(IAsyncEnumerable<int>), x => x, CancellationToken.None).AsTask());
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxByWithTiesAsync(Return42, default(Func<int, int>), CancellationToken.None).AsTask());
+
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxByWithTiesAsync(default(IAsyncEnumerable<int>), x => x, Comparer<int>.Default, CancellationToken.None).AsTask());
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MaxByWithTiesAsync(Return42, default(Func<int, int>), Comparer<int>.Default, CancellationToken.None).AsTask());
+        }
+
+        [Fact]
+        public async Task MaxByWithTies1Async()
+        {
+            var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MaxByWithTiesAsync(x => x / 2);
+            var res = await xs;
+
+            Assert.True(res.SequenceEqual([7, 6]));
+        }
+
+        [Fact]
+        public async Task MaxByWithTies2()
+        {
+            var xs = Array.Empty<int>().ToAsyncEnumerable().MaxByWithTiesAsync(x => x / 2);
+
+            await AssertThrowsAsync<InvalidOperationException>(xs.AsTask());
+        }
+
+        [Fact]
+        public async Task MaxByWithTies3()
+        {
+            var ex = new Exception("Bang!");
+            var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MaxByWithTiesAsync(x => { if (x == 3) throw ex; return x; });
+
+            await AssertThrowsAsync(xs, ex);
+        }
+
+        [Fact]
+        public async Task MaxByWithTies4()
+        {
+            var ex = new Exception("Bang!");
+            var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MaxByWithTiesAsync(x => { if (x == 4) throw ex; return x; });
+
+            await AssertThrowsAsync(xs, ex);
+        }
+
+        [Fact]
+        public async Task MaxByWithTies5()
+        {
+            var ex = new Exception("Bang!");
+            var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().Concat(Throw<int>(ex)).MaxByWithTiesAsync(x => x, Comparer<int>.Default);
+
+            await AssertThrowsAsync(xs, ex);
+        }
+    }
+}

+ 76 - 0
Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/MinByWithTies.cs

@@ -0,0 +1,76 @@
+// 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Tests
+{
+    public class MinByWithTies : AsyncEnumerableExTests
+    {
+        [Fact]
+        public async Task MinByWithTies_Null()
+        {
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinByWithTiesAsync(default(IAsyncEnumerable<int>), x => x).AsTask());
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinByWithTiesAsync(Return42, default(Func<int, int>)).AsTask());
+
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinByWithTiesAsync(default(IAsyncEnumerable<int>), x => x, Comparer<int>.Default).AsTask());
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinByWithTiesAsync(Return42, default(Func<int, int>), Comparer<int>.Default).AsTask());
+
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinByWithTiesAsync(default(IAsyncEnumerable<int>), x => x, CancellationToken.None).AsTask());
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinByWithTiesAsync(Return42, default(Func<int, int>), CancellationToken.None).AsTask());
+
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinByWithTiesAsync(default(IAsyncEnumerable<int>), x => x, Comparer<int>.Default, CancellationToken.None).AsTask());
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerableEx.MinByWithTiesAsync(Return42, default(Func<int, int>), Comparer<int>.Default, CancellationToken.None).AsTask());
+        }
+
+        [Fact]
+        public async Task MinByWithTies1Async()
+        {
+            var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MinByWithTiesAsync(x => x / 2);
+            var res = await xs;
+
+            Assert.True(res.SequenceEqual([3, 2]));
+        }
+
+        [Fact]
+        public async Task MinByWithTies2Async()
+        {
+            var xs = Array.Empty<int>().ToAsyncEnumerable().MinByWithTiesAsync(x => x / 2);
+
+            await AssertThrowsAsync<InvalidOperationException>(xs.AsTask());
+        }
+
+        [Fact]
+        public async Task MinByWithTies3Async()
+        {
+            var ex = new Exception("Bang!");
+            var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MinByWithTiesAsync(x => { if (x == 3) throw ex; return x; });
+
+            await AssertThrowsAsync(xs, ex);
+        }
+
+        [Fact]
+        public async Task MinByWithTies4Async()
+        {
+            var ex = new Exception("Bang!");
+            var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MinByWithTiesAsync(x => { if (x == 4) throw ex; return x; });
+
+            await AssertThrowsAsync(xs, ex);
+        }
+
+        [Fact]
+        public async Task MinByWithTies5Async()
+        {
+            var ex = new Exception("Bang!");
+            var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().Concat(Throw<int>(ex)).MinByWithTiesAsync(x => x, Comparer<int>.Default);
+
+            await AssertThrowsAsync(xs, ex);
+        }
+    }
+}

+ 24 - 0
Ix.NET/Source/System.Interactive.Async/System.Interactive.Async.csproj

@@ -33,6 +33,30 @@
     <EmbeddedResource Include="Properties\System.Interactive.Async.rd.xml" />
   </ItemGroup>
 
+  <!--
+  Incorporate the reference assemblies. Note that these have a different set of TFMs from the proper assemblies.
+  
+  See ../../Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md
+  -->
+  <ItemGroup>
+    <None Include="../refs/System.Interactive.Async/bin/$(Configuration)/**/System.Interactive.Async.*" PackagePath="ref/" Pack="true" />
+  </ItemGroup>
+  
+  <!--
+  These warnings occur because we are deliberately creating a lib/ref mismatch. There doesn't seem to be
+  an official way to do that, so we have to suppress the warnings.
+  
+  See ../../Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md for an explanation of this bizarreness.
+  -->
+
+  <PropertyGroup>
+    <!--
+    NU5128: lib/ref mismatch. This is deliberate, as explained in the ADR.
+    NU5131: spurious missing file errors. It appears that the build is confused by what we're doing.
+    -->
+    <NoWarn>$(NoWarn);NU5128;NU5131</NoWarn>
+  </PropertyGroup>
+
   <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
     <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0" />
   </ItemGroup>

+ 6 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Distinct.cs

@@ -20,6 +20,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence only containing the distinct elements, based on a computed key value, from the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>
+        [Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality of selector-based overloads of Distinct now exists as DistinctBy.")]
         public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
         {
             if (source == null)
@@ -41,6 +42,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence only containing the distinct elements, based on a computed key value, from the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
         /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>
+        [Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality of selector-based overloads of Distinct now exists as DistinctBy.")]
         public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
         {
             if (source == null)
@@ -61,6 +63,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence only containing the distinct elements, based on a computed key value, from the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>
+        [Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality of selector-based overloads of Distinct now exists as DistinctBy.")]
         public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector)
         {
             if (source == null)
@@ -82,6 +85,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence only containing the distinct elements, based on a computed key value, from the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>
+        [Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality of selector-based overloads of Distinct now exists as DistinctBy.")]
         public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector)
         {
             if (source == null)
@@ -104,6 +108,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence only containing the distinct elements, based on a computed key value, from the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
         /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>
+        [Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality of selector-based overloads of Distinct now exists as DistinctBy.")]
         public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IEqualityComparer<TKey>? comparer)
         {
             if (source == null)
@@ -126,6 +131,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence only containing the distinct elements, based on a computed key value, from the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
         /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>
+        [Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality of selector-based overloads of Distinct now exists as DistinctBy.")]
         public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IEqualityComparer<TKey>? comparer)
         {
             if (source == null)

+ 2 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Max.cs

@@ -10,6 +10,7 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerableEx
     {
+#if !REFERENCE_ASSEMBLY
         /// <summary>
         /// Returns the maximum value in an async-enumerable sequence according to the specified comparer.
         /// </summary>
@@ -51,5 +52,6 @@ namespace System.Linq
                 return max;
             }
         }
+#endif
     }
 }

+ 3 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/MaxBy.cs

@@ -10,6 +10,7 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerableEx
     {
+#if !REFERENCE_ASSEMBLY
         /// <summary>
         /// Returns the elements in an async-enumerable sequence with the maximum key value.
         /// </summary>
@@ -164,6 +165,8 @@ namespace System.Linq
 
             return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue), cancellationToken);
         }
+#endif
+
 #endif
     }
 }

+ 169 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/MaxByWithTies.cs

@@ -0,0 +1,169 @@
+// 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;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerableEx
+    {
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the maximum key value.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the maximum elements for.</param>
+        /// <param name="keySelector">Key selector function.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a maximum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MaxByWithTiesCore(source, keySelector, comparer: null, cancellationToken);
+        }
+
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the maximum key value according to the specified comparer.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the maximum elements for.</param>
+        /// <param name="keySelector">Key selector function.</param>
+        /// <param name="comparer">Comparer used to compare key values.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a maximum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MaxByWithTiesCore(source, keySelector, comparer, cancellationToken);
+        }
+
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the maximum key value.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the maximum elements for.</param>
+        /// <param name="keySelector">Key selector function returning a key possibly asynchronously.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a maximum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MaxByWithTiesCore<TSource, TKey>(source, keySelector, comparer: null, cancellationToken);
+        }
+
+#if !NO_DEEP_CANCELLATION
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the maximum key value.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the maximum elements for.</param>
+        /// <param name="keySelector">Key selector function returning a key possibly asynchronously and supporting cancellation.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a maximum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MaxByWithTiesCore<TSource, TKey>(source, keySelector, comparer: null, cancellationToken);
+        }
+#endif
+
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the maximum key value according to the specified comparer.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the maximum elements for.</param>
+        /// <param name="keySelector">Key selector function returning a key possibly asynchronously.</param>
+        /// <param name="comparer">Comparer used to compare key values.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a maximum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MaxByWithTiesCore(source, keySelector, comparer, cancellationToken);
+        }
+
+#if !NO_DEEP_CANCELLATION
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the maximum key value according to the specified comparer.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the maximum elements for.</param>
+        /// <param name="keySelector">Key selector function returning a key possibly asynchronously and supporting cancellation.</param>
+        /// <param name="comparer">Comparer used to compare key values.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a maximum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MaxByWithTiesCore(source, keySelector, comparer, cancellationToken);
+        }
+#endif
+
+        private static ValueTask<IList<TSource>> MaxByWithTiesCore<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken)
+        {
+            comparer ??= Comparer<TKey>.Default;
+
+            return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue), cancellationToken);
+        }
+
+        private static ValueTask<IList<TSource>> MaxByWithTiesCore<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken)
+        {
+            comparer ??= Comparer<TKey>.Default;
+
+            return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue), cancellationToken);
+        }
+
+#if !NO_DEEP_CANCELLATION
+        private static ValueTask<IList<TSource>> MaxByWithTiesCore<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken)
+        {
+            comparer ??= Comparer<TKey>.Default;
+
+            return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue), cancellationToken);
+        }
+#endif
+    }
+}

+ 2 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Min.cs

@@ -10,6 +10,7 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerableEx
     {
+#if !REFERENCE_ASSEMBLY
         /// <summary>
         /// Returns the minimum element in an async-enumerable sequence according to the specified comparer.
         /// </summary>
@@ -51,5 +52,6 @@ namespace System.Linq
                 return min;
             }
         }
+#endif
     }
 }

+ 1 - 105
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/MinBy.cs

@@ -10,6 +10,7 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerableEx
     {
+#if !REFERENCE_ASSEMBLY
         /// <summary>
         /// Returns the elements in an async-enumerable sequence with the minimum key value.
         /// </summary>
@@ -166,111 +167,6 @@ namespace System.Linq
         }
 #endif
 
-        private static async ValueTask<IList<TSource>> ExtremaBy<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> compare, CancellationToken cancellationToken)
-        {
-            var result = new List<TSource>();
-
-            await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
-            {
-                if (!await e.MoveNextAsync())
-                    throw Error.NoElements();
-
-                var current = e.Current;
-                var resKey = keySelector(current);
-                result.Add(current);
-
-                while (await e.MoveNextAsync())
-                {
-                    var cur = e.Current;
-                    var key = keySelector(cur);
-
-                    var cmp = compare(key, resKey);
-
-                    if (cmp == 0)
-                    {
-                        result.Add(cur);
-                    }
-                    else if (cmp > 0)
-                    {
-                        result = [cur];
-                        resKey = key;
-                    }
-                }
-            }
-
-            return result;
-        }
-
-        private static async ValueTask<IList<TSource>> ExtremaBy<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TKey, TKey, int> compare, CancellationToken cancellationToken)
-        {
-            var result = new List<TSource>();
-
-            await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
-            {
-                if (!await e.MoveNextAsync())
-                    throw Error.NoElements();
-
-                var current = e.Current;
-                var resKey = await keySelector(current).ConfigureAwait(false);
-                result.Add(current);
-
-                while (await e.MoveNextAsync())
-                {
-                    var cur = e.Current;
-                    var key = await keySelector(cur).ConfigureAwait(false);
-
-                    var cmp = compare(key, resKey);
-
-                    if (cmp == 0)
-                    {
-                        result.Add(cur);
-                    }
-                    else if (cmp > 0)
-                    {
-                        result = [cur];
-                        resKey = key;
-                    }
-                }
-            }
-
-            return result;
-        }
-
-#if !NO_DEEP_CANCELLATION
-        private static async ValueTask<IList<TSource>> ExtremaBy<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TKey, TKey, int> compare, CancellationToken cancellationToken)
-        {
-            var result = new List<TSource>();
-
-            await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
-            {
-                if (!await e.MoveNextAsync())
-                    throw Error.NoElements();
-
-                var current = e.Current;
-                var resKey = await keySelector(current, cancellationToken).ConfigureAwait(false);
-                result.Add(current);
-
-                while (await e.MoveNextAsync())
-                {
-                    var cur = e.Current;
-                    var key = await keySelector(cur, cancellationToken).ConfigureAwait(false);
-
-                    var cmp = compare(key, resKey);
-
-                    if (cmp == 0)
-                    {
-                        result.Add(cur);
-                    }
-                    else if (cmp > 0)
-                    {
-                        result = [cur];
-                        resKey = key;
-                    }
-                }
-            }
-
-            return result;
-        }
 #endif
     }
 }

+ 276 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/MinByWithTies.cs

@@ -0,0 +1,276 @@
+// 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;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerableEx
+    {
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the minimum key value.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the minimum elements for.</param>
+        /// <param name="keySelector">Key selector function.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a minimum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MinByWithTiesCore(source, keySelector, comparer: null, cancellationToken);
+        }
+
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the minimum key value according to the specified comparer.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the minimum elements for.</param>
+        /// <param name="keySelector">Key selector function.</param>
+        /// <param name="comparer">Comparer used to compare key values.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a minimum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MinByWithTiesCore(source, keySelector, comparer, cancellationToken);
+        }
+
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the minimum key value.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the minimum elements for.</param>
+        /// <param name="keySelector">Key selector function returning a key possibly asynchronously.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a minimum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MinByWithTiesCore<TSource, TKey>(source, keySelector, comparer: null, cancellationToken);
+        }
+
+#if !NO_DEEP_CANCELLATION
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the minimum key value.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the minimum elements for.</param>
+        /// <param name="keySelector">Key selector function returning a key possibly asynchronously and supporting cancellation.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a minimum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MinByWithTiesCore<TSource, TKey>(source, keySelector, comparer: null, cancellationToken);
+        }
+#endif
+
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the minimum key value according to the specified comparer.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the minimum elements for.</param>
+        /// <param name="keySelector">Key selector function returning a key possibly asynchronously.</param>
+        /// <param name="comparer">Comparer used to compare key values.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a minimum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MinByWithTiesCore(source, keySelector, comparer, cancellationToken);
+        }
+
+#if !NO_DEEP_CANCELLATION
+        /// <summary>
+        /// Returns the elements in an async-enumerable sequence with the minimum key value according to the specified comparer.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence to get the minimum elements for.</param>
+        /// <param name="keySelector">Key selector function returning a key possibly asynchronously and supporting cancellation.</param>
+        /// <param name="comparer">Comparer used to compare key values.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing a list of zero or more elements that have a minimum key value.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        public static ValueTask<IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (keySelector == null)
+                throw Error.ArgumentNull(nameof(keySelector));
+
+            return MinByWithTiesCore(source, keySelector, comparer, cancellationToken);
+        }
+#endif
+
+        private static ValueTask<IList<TSource>> MinByWithTiesCore<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken)
+        {
+            comparer ??= Comparer<TKey>.Default;
+
+            return ExtremaBy(source, keySelector, (key, minValue) => -comparer.Compare(key, minValue), cancellationToken);
+        }
+
+        private static ValueTask<IList<TSource>> MinByWithTiesCore<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken)
+        {
+            comparer ??= Comparer<TKey>.Default;
+
+            return ExtremaBy(source, keySelector, (key, minValue) => -comparer.Compare(key, minValue), cancellationToken);
+        }
+
+#if !NO_DEEP_CANCELLATION
+        private static ValueTask<IList<TSource>> MinByWithTiesCore<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, CancellationToken cancellationToken)
+        {
+            comparer ??= Comparer<TKey>.Default;
+
+            return ExtremaBy(source, keySelector, (key, minValue) => -comparer.Compare(key, minValue), cancellationToken);
+        }
+#endif
+
+        private static async ValueTask<IList<TSource>> ExtremaBy<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> compare, CancellationToken cancellationToken)
+        {
+            var result = new List<TSource>();
+
+            await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+            {
+                if (!await e.MoveNextAsync())
+                    throw Error.NoElements();
+
+                var current = e.Current;
+                var resKey = keySelector(current);
+                result.Add(current);
+
+                while (await e.MoveNextAsync())
+                {
+                    var cur = e.Current;
+                    var key = keySelector(cur);
+
+                    var cmp = compare(key, resKey);
+
+                    if (cmp == 0)
+                    {
+                        result.Add(cur);
+                    }
+                    else if (cmp > 0)
+                    {
+                        result = [cur];
+                        resKey = key;
+                    }
+                }
+            }
+
+            return result;
+        }
+
+        private static async ValueTask<IList<TSource>> ExtremaBy<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TKey, TKey, int> compare, CancellationToken cancellationToken)
+        {
+            var result = new List<TSource>();
+
+            await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+            {
+                if (!await e.MoveNextAsync())
+                    throw Error.NoElements();
+
+                var current = e.Current;
+                var resKey = await keySelector(current).ConfigureAwait(false);
+                result.Add(current);
+
+                while (await e.MoveNextAsync())
+                {
+                    var cur = e.Current;
+                    var key = await keySelector(cur).ConfigureAwait(false);
+
+                    var cmp = compare(key, resKey);
+
+                    if (cmp == 0)
+                    {
+                        result.Add(cur);
+                    }
+                    else if (cmp > 0)
+                    {
+                        result = [cur];
+                        resKey = key;
+                    }
+                }
+            }
+
+            return result;
+        }
+
+#if !NO_DEEP_CANCELLATION
+        private static async ValueTask<IList<TSource>> ExtremaBy<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TKey, TKey, int> compare, CancellationToken cancellationToken)
+        {
+            var result = new List<TSource>();
+
+            await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+            {
+                if (!await e.MoveNextAsync())
+                    throw Error.NoElements();
+
+                var current = e.Current;
+                var resKey = await keySelector(current, cancellationToken).ConfigureAwait(false);
+                result.Add(current);
+
+                while (await e.MoveNextAsync())
+                {
+                    var cur = e.Current;
+                    var key = await keySelector(cur, cancellationToken).ConfigureAwait(false);
+
+                    var cmp = compare(key, resKey);
+
+                    if (cmp == 0)
+                    {
+                        result.Add(cur);
+                    }
+                    else if (cmp > 0)
+                    {
+                        result = [cur];
+                        resKey = key;
+                    }
+                }
+            }
+
+            return result;
+        }
+#endif
+    }
+}

+ 1 - 1
Ix.NET/Source/System.Interactive.Providers/System.Interactive.Providers.csproj

@@ -21,7 +21,7 @@
   See ../../Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md
   -->
   <ItemGroup>
-    <None Include="../refs/System.Interactive.Providers/bin/$(Configuration)/$(TargetFramework)/**" PackagePath="ref/$(TargetFramework)" Pack="true" />
+    <None Include="../refs/System.Interactive.Providers/bin/$(Configuration)/**/System.Interactive.Providers.*" PackagePath="ref/" Pack="true" />
   </ItemGroup>
 
   <!--

+ 1 - 1
Ix.NET/Source/System.Interactive/System.Interactive.csproj

@@ -18,7 +18,7 @@
   See ../../Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md
   -->
   <ItemGroup>
-    <None Include="../refs/System.Interactive/bin/$(Configuration)/$(TargetFramework)/**" PackagePath="ref/$(TargetFramework)" Pack="true" />
+    <None Include="../refs/System.Interactive/bin/$(Configuration)/**/System.Interactive.*" PackagePath="ref/" Pack="true" />
   </ItemGroup>
 
   <!--

+ 1 - 1
Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs

@@ -36,7 +36,7 @@ namespace System.Linq.Async.SourceGenerator
             var attributeSymbol = GetAsyncOverloadAttributeSymbol(context);
             var methodsBySyntaxTree = GetMethodsGroupedBySyntaxTree(context, syntaxReceiver);
 
-            foreach (var grouping in methodsBySyntaxTree)
+            foreach (var grouping in methodsBySyntaxTree.Where(g => g.Methods.Any()))
                 context.AddSource(
                     $"{Path.GetFileNameWithoutExtension(grouping.SyntaxTree.FilePath)}.AsyncOverloads",
                     GenerateOverloads(grouping, options, context, attributeSymbol));

+ 1 - 1
Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj

@@ -24,7 +24,7 @@
     <!--
     Incorporate the reference assemblies.
     -->
-    <None Include="../refs/System.Linq.Async/bin/$(Configuration)/$(TargetFramework)/**" PackagePath="ref/$(TargetFramework)" Pack="true" />
+    <None Include="../refs/System.Linq.Async/bin/$(Configuration)/**/System.Linq.Async.*" PackagePath="ref/" Pack="true" />
   </ItemGroup>
 
   <PropertyGroup>

+ 30 - 0
Ix.NET/Source/Tests.System.Interactive.ApiApprovals/Api/ApiApprovalTests.SystemInteractiveAsync.verified.cs

@@ -57,11 +57,29 @@ namespace System.Linq
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Defer<TSource>(System.Func<System.Collections.Generic.IAsyncEnumerable<TSource>> factory) { }
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Defer<TSource>(System.Func<System.Threading.Tasks.Task<System.Collections.Generic.IAsyncEnumerable<TSource>>> factory) { }
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Defer<TSource>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<System.Collections.Generic.IAsyncEnumerable<TSource>>> factory) { }
+        [System.Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and" +
+            " the functionality of selector-based overloads of Distinct now exists as Distinc" +
+            "tBy.")]
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>> keySelector) { }
+        [System.Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and" +
+            " the functionality of selector-based overloads of Distinct now exists as Distinc" +
+            "tBy.")]
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, TKey> keySelector) { }
+        [System.Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and" +
+            " the functionality of selector-based overloads of Distinct now exists as Distinc" +
+            "tBy.")]
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>> keySelector) { }
+        [System.Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and" +
+            " the functionality of selector-based overloads of Distinct now exists as Distinc" +
+            "tBy.")]
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { }
+        [System.Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and" +
+            " the functionality of selector-based overloads of Distinct now exists as Distinc" +
+            "tBy.")]
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { }
+        [System.Obsolete("Use DistinctBy.  IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and" +
+            " the functionality of selector-based overloads of Distinct now exists as Distinc" +
+            "tBy.")]
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { }
         public static System.Collections.Generic.IAsyncEnumerable<TSource> DistinctUntilChanged<TSource>(this System.Collections.Generic.IAsyncEnumerable<TSource> source) { }
         public static System.Collections.Generic.IAsyncEnumerable<TSource> DistinctUntilChanged<TSource>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { }
@@ -99,6 +117,12 @@ namespace System.Linq
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Merge<TSource>(this System.Collections.Generic.IAsyncEnumerable<System.Collections.Generic.IAsyncEnumerable<TSource>> sources) { }
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Merge<TSource>(params System.Collections.Generic.IAsyncEnumerable<TSource>[] sources) { }
         public static System.Collections.Generic.IAsyncEnumerable<TSource> Merge<TSource>(this System.Collections.Generic.IEnumerable<System.Collections.Generic.IAsyncEnumerable<TSource>> sources) { }
@@ -109,6 +133,12 @@ namespace System.Linq
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IComparer<TKey> comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Collections.Generic.IAsyncEnumerable<TSource> source, System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>> keySelector, System.Collections.Generic.IComparer<TKey> comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Collections.Generic.IAsyncEnumerable<TValue> Never<TValue>() { }
         public static System.Collections.Generic.IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(params System.Collections.Generic.IAsyncEnumerable<TSource>[] sources) { }
         public static System.Collections.Generic.IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(this System.Collections.Generic.IEnumerable<System.Collections.Generic.IAsyncEnumerable<TSource>> sources) { }

+ 43 - 0
Ix.NET/Source/Tests.System.Interactive.ApiApprovals/Api/ApiApprovalTests.SystemInteractiveAsyncProviders.verified.cs

@@ -8,6 +8,37 @@ namespace System.Linq
     public static class AsyncQueryableEx
     {
         public static System.Linq.IAsyncQueryable<TSource> Amb<TSource>(this System.Linq.IAsyncQueryable<TSource> first, System.Collections.Generic.IAsyncEnumerable<TSource> second) { }
+        public static System.Linq.IAsyncQueryable<TSource> AsAsyncEnumerable<TSource>(this System.Linq.IAsyncQueryable<TSource> source) { }
+        public static System.Threading.Tasks.ValueTask<decimal> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<decimal>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<decimal?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<decimal?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<double>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<double?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<float> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<float>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<float?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<float?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<int>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<int?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<long>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<long?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<decimal> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, decimal>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<decimal?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, decimal?>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, double>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, double?>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<float> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, float>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<float?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, float?>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, int>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, int?>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, long>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, long?>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<decimal> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<decimal>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<decimal?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<decimal?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<double>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<double?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<float> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<float>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<float?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<float?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<int>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<int?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<long>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<double?> AverageAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<long?>>> selector, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Linq.IAsyncQueryable<System.Collections.Generic.IList<TSource>> Buffer<TSource>(this System.Linq.IAsyncQueryable<TSource> source, int count) { }
         public static System.Linq.IAsyncQueryable<System.Collections.Generic.IList<TSource>> Buffer<TSource>(this System.Linq.IAsyncQueryable<TSource> source, int count, int skip) { }
         public static System.Linq.IAsyncQueryable<TSource> Catch<TSource>(this System.Linq.IAsyncQueryable<TSource> first, System.Collections.Generic.IAsyncEnumerable<TSource> second) { }
@@ -56,6 +87,12 @@ namespace System.Linq
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, TKey>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MaxByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Linq.IAsyncQueryable<TSource> Merge<TSource>(this System.Linq.IAsyncQueryable<System.Collections.Generic.IAsyncEnumerable<TSource>> sources) { }
         public static System.Threading.Tasks.ValueTask<TSource> MinAsync<TSource>(this System.Linq.IAsyncQueryable<TSource> source, System.Collections.Generic.IComparer<TSource>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
@@ -64,6 +101,12 @@ namespace System.Linq
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, TKey>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, TKey>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
+        public static System.Threading.Tasks.ValueTask<System.Collections.Generic.IList<TSource>> MinByWithTiesAsync<TSource, TKey>(this System.Linq.IAsyncQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<TKey>>> keySelector, System.Collections.Generic.IComparer<TKey>? comparer, System.Threading.CancellationToken cancellationToken = default) { }
         public static System.Linq.IAsyncQueryable<TSource> OnErrorResumeNext<TSource>(this System.Linq.IAsyncQueryable<TSource> first, System.Collections.Generic.IAsyncEnumerable<TSource> second) { }
         public static System.Linq.IAsyncQueryable<TSource> Repeat<TSource>(this System.Linq.IAsyncQueryable<TSource> source) { }
         public static System.Linq.IAsyncQueryable<TSource> Repeat<TSource>(this System.Linq.IAsyncQueryable<TSource> source, int count) { }

+ 44 - 0
Ix.NET/Source/refs/System.Interactive.Async/System.Interactive.Async.csproj

@@ -0,0 +1,44 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <ProduceOnlyReferenceAssembly>true</ProduceOnlyReferenceAssembly>
+    
+    <Description>Interactive Extensions Async Library used to express queries over asynchronous enumerable sequences.</Description>
+    <AssemblyTitle>Interactive Extensions - Async Library</AssemblyTitle>
+    <Authors>Microsoft</Authors>
+
+    <!--
+    This TFM list does not match the main project. That is deliberate.
+  
+    See ../../Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md
+
+    .NET 10.0 gets its own target because that doesn't need a transitive reference
+    to System.Linq.AsyncEnumerable - it's built in from .NET 10.0 and later -
+    but all other targets do need that reference.
+    Even though we support back to .NET 8.0 for v7, we don't build targets for
+    any versions older than net10.0 because net8.0 and net9.0 are both covered
+    by the netstandard2.0 target.
+    -->
+    <TargetFrameworks>net48;netstandard2.1;net6.0;net10.0</TargetFrameworks>
+    <PackageTags>Ix;Interactive;Extensions;Enumerable;Asynchronous</PackageTags>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Compile Include="..\..\System.Interactive.Async\**\*.cs" Exclude="..\..\System.Interactive.Async\obj\**" />
+
+    <Compile Include="..\..\System.Linq.Async\System\Error.cs" Link="System\Error.cs" />
+    <Compile Include="..\..\System.Linq.Async\System\Linq\AsyncIterator.cs" Link="System\Linq\AsyncIterator.cs" />
+    <Compile Include="..\..\System.Linq.Async\System\Linq\Set.cs" Link="System\Linq\Set.cs" />
+    <Compile Include="..\..\System.Linq.Async\System\Strings.cs" Link="System\Strings.cs" />
+    <Compile Include="..\..\System.Linq.Async\System\Threading\Tasks\AsyncEnumerableExt.cs" Link="System\Threading\Tasks\AsyncEnumerableExt.cs" />
+  </ItemGroup>
+
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\System.Linq.Async.SourceGenerator\System.Linq.Async.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" Private="false" />
+  </ItemGroup>
+
+</Project>