Răsfoiți Sursa

Preparing for System.Linq.AsyncEnumerable (#2240)

* Update to .NET 10.0, add System.Linq.AsyncEnumerable refs
* Hide methods that are now dups
* Move methods not duplicated into `System.Interactive.Async`
Ian Griffiths 1 săptămână în urmă
părinte
comite
1ce85f4066
100 a modificat fișierele cu 2486 adăugiri și 304 ștergeri
  1. 71 0
      Ix.NET/Documentation/adr/0002-System-Linq-Async-In-Net10.md
  2. 14 0
      Ix.NET/Source/ApiCompare/ApiCompare.csproj
  3. 1 1
      Ix.NET/Source/Directory.Build.props
  4. 1 1
      Ix.NET/Source/FasterLinq/FasterLinq.csproj
  5. 18 0
      Ix.NET/Source/Playground/Playground.csproj
  6. 21 3
      Ix.NET/Source/System.Interactive.Async.Providers.Tests/System.Interactive.Async.Providers.Tests.csproj
  7. 1 1
      Ix.NET/Source/System.Interactive.Async.Providers/System.Interactive.Async.Providers.csproj
  8. 1 1
      Ix.NET/Source/System.Interactive.Async.Tests/AsyncTests.Bugs.cs
  9. 25 4
      Ix.NET/Source/System.Interactive.Async.Tests/System.Interactive.Async.Tests.csproj
  10. 4 4
      Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/Amb.cs
  11. 4 4
      Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/Timeout.cs
  12. 2 2
      Ix.NET/Source/System.Interactive.Async.Tests/TaskExtTests.cs
  13. 35 3
      Ix.NET/Source/System.Interactive.Async/System.Interactive.Async.csproj
  14. 52 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/IAsyncIListProvider.cs
  15. 26 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/AsAsyncEnumerable.cs
  16. 514 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Average.Generated.cs
  17. 155 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Average.Generated.tt
  18. 23 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Disposables.cs
  19. 6 6
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Scan.cs
  20. 222 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/ToAsyncEnumerable.Observable.cs
  21. 48 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/ToAsyncEnumerable.Task.cs
  22. 83 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/ToObservable.cs
  23. 7 0
      Ix.NET/Source/System.Interactive.Async/TaskExt.cs
  24. 2 4
      Ix.NET/Source/System.Interactive.Providers/System.Interactive.Providers.csproj
  25. 7 4
      Ix.NET/Source/System.Interactive.Tests/System.Interactive.Tests.csproj
  26. 2 4
      Ix.NET/Source/System.Interactive/System.Interactive.csproj
  27. 25 4
      Ix.NET/Source/System.Linq.Async.Queryable.Tests/System.Linq.Async.Queryable.Tests.csproj
  28. 23 1
      Ix.NET/Source/System.Linq.Async.Queryable/System.Linq.Async.Queryable.csproj
  29. 30 7
      Ix.NET/Source/System.Linq.Async.SourceGenerator/AsyncOverloadsGenerator.cs
  30. 12 0
      Ix.NET/Source/System.Linq.Async.SourceGenerator/Properties/launchSettings.json
  31. 1 0
      Ix.NET/Source/System.Linq.Async.SourceGenerator/System.Linq.Async.SourceGenerator.csproj
  32. 39 4
      Ix.NET/Source/System.Linq.Async.Tests/System.Linq.Async.Tests.csproj
  33. 3 2
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Range.cs
  34. 4 2
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Reverse.cs
  35. 6 3
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Select.cs
  36. 18 12
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Skip.cs
  37. 18 12
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Take.cs
  38. 6 6
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToAsyncEnumerable.cs
  39. 2 2
      Ix.NET/Source/System.Linq.Async.Tests/ValueTaskHelpers.cs
  40. 49 3
      Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj
  41. 2 0
      Ix.NET/Source/System.Linq.Async/System/Linq/AsyncEnumerablePartition.cs
  42. 2 0
      Ix.NET/Source/System.Linq.Async/System/Linq/AsyncListPartition.cs
  43. 6 0
      Ix.NET/Source/System.Linq.Async/System/Linq/IAsyncGrouping.cs
  44. 9 0
      Ix.NET/Source/System.Linq.Async/System/Linq/IAsyncIListProvider.cs
  45. 2 0
      Ix.NET/Source/System.Linq.Async/System/Linq/IOrderedAsyncEnumerable.cs
  46. 30 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Aggregate.cs
  47. 6 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/All.cs
  48. 7 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Any.cs
  49. 6 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/AppendPrepend.cs
  50. 8 1
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/AsAsyncEnumerable.cs
  51. 59 14
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Average.Generated.cs
  52. 19 2
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Average.Generated.tt
  53. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Cast.cs
  54. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Concat.cs
  55. 7 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Contains.cs
  56. 15 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Count.cs
  57. 2 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/DefaultIfEmpty.cs
  58. 6 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Distinct.cs
  59. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ElementAt.cs
  60. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ElementAtOrDefault.cs
  61. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Empty.cs
  62. 6 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Except.cs
  63. 11 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/First.cs
  64. 10 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/FirstOrDefault.cs
  65. 6 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ForEach.cs
  66. 47 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/GroupBy.cs
  67. 9 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/GroupJoin.cs
  68. 5 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Intersect.cs
  69. 11 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Join.cs
  70. 9 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Last.cs
  71. 10 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/LastOrDefault.cs
  72. 8 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/LongCount.cs
  73. 15 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Max.cs
  74. 15 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Min.cs
  75. 231 83
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/MinMax.Generated.cs
  76. 38 1
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/MinMax.Generated.tt
  77. 6 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/OfType.cs
  78. 55 1
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/OrderBy.cs
  79. 2 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/OrderedAsyncEnumerable.cs
  80. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Range.cs
  81. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Repeat.cs
  82. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Reverse.cs
  83. 10 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Select.cs
  84. 24 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SelectMany.cs
  85. 5 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SequenceEqual.cs
  86. 8 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Single.cs
  87. 8 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SingleOrDefault.cs
  88. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Skip.cs
  89. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SkipLast.cs
  90. 10 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SkipWhile.cs
  91. 50 100
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Sum.Generated.cs
  92. 9 2
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Sum.Generated.tt
  93. 5 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Take.cs
  94. 5 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/TakeLast.cs
  95. 10 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/TakeWhile.cs
  96. 4 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToArray.cs
  97. 8 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToAsyncEnumerable.Observable.cs
  98. 7 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToAsyncEnumerable.Task.cs
  99. 2 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToAsyncEnumerable.cs
  100. 20 0
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToDictionary.cs

+ 71 - 0
Ix.NET/Documentation/adr/0002-System-Linq-Async-In-Net10.md

@@ -0,0 +1,71 @@
+# Migration of core `IAsyncEnumerable<T>` LINQ to runtime libraries
+
+.NET 10.0 provides LINQ support for `IAsyncEnumerable<T>` in the runtime class libraries. This effectively renders most of `System.Linq.Async` irrelevant. However, enabling a smooth transition to .NET 10.0 for existing users of this library is not entirely straightforward. This document describes how this will work.
+
+## Status
+
+Proposed.
+
+## Authors
+
+@idg10 ([Ian Griffiths](https://endjin.com/who-we-are/our-people/ian-griffiths/))
+
+
+## Context
+
+As an accident of history, the Rx.NET repository ended up being the de facto implementation of LINQ for `IAsyncEnumerable<T>` from 2019 when .NET Core 3 shipped up until late 2025 when .NET 10 shipped.
+
+This happened because Rx.NET had effectively been the incubator in which `IAsyncEnumerable<T>` was originally developed. Back before .NET Core 3.0, there was no such interface built into .NET, but Rx _did_ define this interface as part of its 'interactive extensions for .NET' feature. It also implemented common LINQ operators for that interface.
+
+.NET Core 3.0 defined its own version of this `IAsyncEnumerable<T>`, but the .NET team did not implement LINQ for it at that time. Since the Rx.NET repository already had a fairly complete implementation of LINQ for its original version of `IAsyncEnumerable<T>`, it was fairly easy to adapt this to the new version of `IAsyncEnumerable<T>` built into .NET. Thus `System.Linq.Async` was born.
+
+In .NET 10.0, the .NET team decided to take ownership of this functionality. For various reasons they did not simply adopt the existing code. (One reason is that .NET class library design guidelines have evolved over time, and some of the methods in Rx's `System.Linq.Async` did not align with those guidelines.) So the .NET team took the decision that they were not going to maintain backwards compatibility with the existing Rx.NET-originated `System.Linq.Async` library. Instead, there is a new `System.Linq.AsyncEnumerable` library that defines equivalent functionality, but implemented from scratch, and fully in conformance with current .NET class library design guidelines.
+
+Most of the API changes fall into one of these categories:
+
+1. Where `System.Linq.Async` defined methods taking an `IComparer<T>` and an associated overload without the `IComparer<T>`, `System.Linq.AsyncEnumerable` only defines the overload that takes the `IComparer<T>`, making it optional with a default value of `null`
+2. For certain operators (e.g. `Min`, `Max`, `Sum`) `System.Linq.Async` defined methods operating directly on numerical sequences, and also ones that operate on sequences of any type, taking an addition argument to project each element to a numeric value; in `System.Linq.AsyncEnumerable`, these projection-based variants either have a different name (e.g. `MaxByAsync`) or simply don't exist (as with `SumAsync`)
+3. `System.Linq.Async` offered some adapters (e.g. `ToEnumerable`, `ToObservable`) that handled async operations in potentially risky ways (sync over async) or ways that embed opinions about how to do it (e.g. `ToObservable` does not provide the caller with any scheduling options); `System.Linq.AsyncEnumerable` has chosen simply not to implement these at all
+4. Operators that accept callbacks (e.g. `Select` and `Where`) can be passed either a normal non-async callback (e.g. `Func<TElement, TResult>` for `Select` or `Func<TElement, bool>` for `Where`), or an `async` callback, in which case the callback returns a `Task<T>` and may support cancellation. `System.Linq.Async` used different names for these methods: it added an `Await` suffix and also a `WithCancellation` suffix to distinguish the forms where the callback takes a cancellation token. `System.Linq.AsyncEnumerable` requires all `async` callbacks to accept a cancellation token (which they are free to ignore of course) and does not use different names for these forms. E.g., in place of `System.Linq.Async`'s `WhereAwait`, `System.Linq.AsyncEnumerable` just offers an additional overload of `Where`.
+
+There are also a couple of cases where functionality simply has not been reproduced. For example, `System.Linq.Async` provides an `AsAsyncEnumerable` to enable deliberate type erasure.
+
+`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.) 
+
+## Decision
+
+The next `System.Linq.Async` 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
+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
+6. mark `IAsyncGrouping` as obsolete
+7. mark the public `IAsyncIListProvider` as obsolete, and define a non-public version for continued internal use in `System.Interactive.Linq`
+8. continue to provide the full `System.Linq.Async` API in the `lib` assemblies to provide binary compatibility
+9. mark the `System.Linq.Async` NuGet package as obsolete, and recommend the use of `System.Linq.AsyncEnumerable` and/or `System.Interactive.Async` instead
+
+The main effect of this is that code that had been using the `System.Linq.Async` implementation of LINQ for `IAsyncEnumerable<T>` will, in most cases, now be using the .NET runtime library implementation if it is rebuilt against this new version of `System.Linq.Async`.
+
+If using .NET 10, developers may find that all they need to do is remove the reference to `System.Linq.Async`. (If using earlier versions of .NET, or .NET FX, they can replace it with a reference to `System.Linq.AsyncEnumerable`.) If they were using any `XxxAwaitAsync` and `XxxAwaitWithCancellationAsync` methods, they will have to change these calls to use the new equivalent overloads.
+
+If developers are using `System.Linq.Async` features that are not available in `System.Linq.AsyncEnumerable`, they should still remove the `System.Linq.Async` reference (since we will be deprecating that package), but they will add a reference to `System.Interactive.Async`. For example, although `System.Linq.AsyncEnumerable` defines `AverageAsync`, it does not offer the same range of functionality as `System.Linq.Async` previously did: overloads taking selectors (both sync and async). These methods become hidden in `System.Linq.Async` (available only for binary compatibility) and they have moved to `AsyncEnumerableEx` in `System.Interactive.Async`. `System.Linq.Async` now adds a transitive reference to `System.Interactive.Async` in order to ensure continued source compatibility until such time as people update their NuGet references.
+
+Developers using the methods we should probably never have provided (the sync-over-async methods such as `ToEnumerable`) will only be able to use these by retaining a reference to the deprecated `System.Linq.Async` package and ignoring or suppressing the obsolete warning. Our position is that these developers should find another approach. Or if they absolutely insist on doing sync-over-async but want to rid their code of obsolete/deprecation warnings, they will have to write their own versions of these methods.
+
+In summary, each of the features previously provided by `System.Linq.Async` will be in one of these categories:
+
+* Method hidden in `ref` assembly, available in `System.Linq.AsyncEnumerable`
+* 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`
+
+## 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.
+
+Code that had been written to use `System.Linq.Async` v6 that upgrades to .NET 10 will automatically move to the .NET runtime library implementation without needing any code changes in cases where the .NET 10 implementation is source-compatible with `System.Linq.Async`. Code using methods where .NET 10 has changed (to comply with current class library design rules) will continue to build and run correctly, but the compiler will warn the developer that they are now using obsolete methods, and these warnings will indicate the recommended replacement. Code using methods in `System.Linq.Async` that .NET 10 has chosen not to provide equivalents for will automatically move to using the `System.Interactive.Async` implementations without needing any code changes. Since the `System.Linq.Async` NuGet package will be marked as obsolete, the developer will know that they should stop using it. If they are not using any of the `Obsolete` methods they will be able to remove the method, and might need to add a reference to `System.Interactive.Async`.
+
+The situation is very similar for code written to use `System.Linq.Async` v6 that does _not_ upgrade to .NET 10 (e.g. either it stays on .NET 8 or 9, or it targets .NET Framework or .NET Standard) but which newly acquires a dependency on `System.Linq.AsyncEnumerable` either because the developer adds it, or because they update to a new version of some component which adds it as a new transitive dependency.
+
+Code written to use `System.Linq.Async` v6 that changes nothing at all but, which is rebuilt after `System.Linq.Async` v7 is released, will see a warning that the package is now deprecated. They can fix this warning by removing the package and adding a reference to `System.Linq.AsyncEnumerable` or `System.Interactive.Async` or both as required.

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

@@ -5,6 +5,20 @@
     <TargetFramework>net8.0</TargetFramework>
   </PropertyGroup>
 
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-rc.1.25451.107"
+                      Aliases="SystemLinqAsyncEnumerable" />
+  </ItemGroup>
+
+  <Target Name="_SetAliasOnBuiltInSystemLinqAsyncEnumerable" BeforeTargets="ResolveAssemblyReferences">
+
+    <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
+      <Reference Condition="'%(Reference.AssemblyName)' == 'System.Linq.AsyncEnumerable'">
+        <Aliases>SystemLinqAsyncEnumerable</Aliases>
+      </Reference>
+    </ItemGroup>
+  </Target>
+
   <ItemGroup>
     <ProjectReference Include="..\System.Interactive.Async.Providers\System.Interactive.Async.Providers.csproj" />
     <ProjectReference Include="..\System.Interactive.Async\System.Interactive.Async.csproj" />

+ 1 - 1
Ix.NET/Source/Directory.Build.props

@@ -38,7 +38,7 @@
   </ItemGroup>
 
   <ItemGroup Condition="'$(IsTestProject)' == 'true'">
-    <PackageReference Include="coverlet.collector" Version="3.2.0" />
+    <PackageReference Include="coverlet.collector" Version="6.0.4" />
   </ItemGroup>
 
 

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

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

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

@@ -14,4 +14,22 @@
     <ProjectReference Include="..\System.Linq.Async\System.Linq.Async.csproj" />
   </ItemGroup>
 
+  <!--
+  Since this includes code that uses the legacy System.Linq.Async package, we need prevent the compiler from using the .NET runtime library
+  System.Linq.AsyncEnumerable package.
+  So although we get this references transitively (or automatically on .NET 10.0+) we need to put them explicitly here to set aliases.
+  -->
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-rc.1.25451.107"
+                      Aliases="SystemLinqAsyncEnumerable" />
+  </ItemGroup>
+
+  <Target Name="_SetAliasOnBuiltInSystemLinqAsyncEnumerable" BeforeTargets="ResolveAssemblyReferences">
+
+    <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
+      <Reference Condition="'%(Reference.AssemblyName)' == 'System.Linq.AsyncEnumerable'">
+        <Aliases>SystemLinqAsyncEnumerable</Aliases>
+      </Reference>
+    </ItemGroup>
+  </Target>
 </Project>

+ 21 - 3
Ix.NET/Source/System.Interactive.Async.Providers.Tests/System.Interactive.Async.Providers.Tests.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net8.0;net6.0</TargetFrameworks>
+    <TargetFrameworks>net48;net10.0;net8.0</TargetFrameworks>
     <NoWarn>$(NoWarn);CS0618</NoWarn>
   </PropertyGroup>
 
@@ -15,10 +15,28 @@
     <ProjectReference Include="..\System.Interactive.Async.Providers\System.Interactive.Async.Providers.csproj" />
     <ProjectReference Include="..\System.Linq.Async\System.Linq.Async.csproj" />
   </ItemGroup>
+  
+  <!--
+  Since this tests the System.Interactive.Async.Providers package, which has a dependency on the legacy System.Linq.Async.Queryable package,
+  we need prevent the compiler from using the .NET runtime library System.Linq.AsyncEnumerable package.
+  So although we get this references transitively (or automatically on .NET 10.0+) we need to put them explicitly here to set aliases.
+  -->
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-rc.1.25451.107" Aliases="SystemLinqAsyncEnumerable" />
+  </ItemGroup>
+
+  <Target Name="_SetAliasOnBuiltInSystemLinqAsyncEnumerable" BeforeTargets="ResolveAssemblyReferences">
+
+    <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
+      <Reference Condition="'%(Reference.AssemblyName)' == 'System.Linq.AsyncEnumerable'">
+        <Aliases>SystemLinqAsyncEnumerable</Aliases>
+      </Reference>
+    </ItemGroup>
+  </Target>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>

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

@@ -3,7 +3,7 @@
   <PropertyGroup>
     <Description>Interactive Extensions Async Providers Library used to build query providers and express queries over async enumerable sequences.</Description>
     <AssemblyTitle>Interactive Extensions - Async Providers Library</AssemblyTitle>
-    <TargetFrameworks>net48;netstandard2.0;netstandard2.1;net6.0</TargetFrameworks>
+    <TargetFrameworks>net48;netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
     <PackageTags>Ix;Interactive;Extensions;Enumerable;Asynchronous</PackageTags>
   </PropertyGroup>
 

+ 1 - 1
Ix.NET/Source/System.Interactive.Async.Tests/AsyncTests.Bugs.cs

@@ -22,7 +22,7 @@ namespace Tests
         }
 
         [Fact]
-        public async void CorrectDispose()
+        public async Task CorrectDispose()
         {
             var disposed = new TaskCompletionSource<bool>();
 

+ 25 - 4
Ix.NET/Source/System.Interactive.Async.Tests/System.Interactive.Async.Tests.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net8.0;net6.0</TargetFrameworks>
+    <TargetFrameworks>net48;net10.0;net8.0</TargetFrameworks>
 
     <!--
       CA1510: Use ArgumentNullException.ThrowIfNull - not available on .NET 4.8
@@ -21,12 +21,33 @@
     <ProjectReference Include="..\System.Interactive.Async.Providers\System.Interactive.Async.Providers.csproj" />
     <ProjectReference Include="..\System.Linq.Async\System.Linq.Async.csproj" />
   </ItemGroup>
+  
+  <!--
+  Since this tests the System.Interactive.Async.Providers package, which has a dependency on the legacy System.Linq.Async.Queryable package,
+  we need prevent the compiler from using the .NET runtime library System.Linq.AsyncEnumerable package.
+  So although we get this references transitively (or automatically on .NET 10.0+) we need to put them explicitly here to set aliases.
+  -->
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-rc.1.25451.107" Aliases="SystemLinqAsyncEnumerable" />
+  </ItemGroup>
+
+  <Target Name="_SetAliasOnBuiltInSystemLinqAsyncEnumerable" BeforeTargets="ResolveAssemblyReferences">
+
+    <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
+      <Reference Condition="'%(Reference.AssemblyName)' == 'System.Linq.AsyncEnumerable'">
+        <Aliases>SystemLinqAsyncEnumerable</Aliases>
+      </Reference>
+    </ItemGroup>
+  </Target>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
     <PackageReference Include="FluentAssertions" Version="6.4.0" />
-    <PackageReference Include="xunit" Version="2.4.1" />
+    <PackageReference Include="xunit" Version="2.9.3" />
   </ItemGroup>
 
   <ItemGroup>

+ 4 - 4
Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/Amb.cs

@@ -242,7 +242,7 @@ namespace Tests
             {
                 await xs.MoveNextAsync();
 
-                Assert.False(true, "Should not have gotten here");
+                Assert.Fail("Should not have gotten here");
             }
             catch (InvalidOperationException)
             {
@@ -265,7 +265,7 @@ namespace Tests
             {
                 await xs.MoveNextAsync();
 
-                Assert.False(true, "Should not have gotten here");
+                Assert.Fail("Should not have gotten here");
             }
             catch (InvalidOperationException)
             {
@@ -292,7 +292,7 @@ namespace Tests
             {
                 await xs.MoveNextAsync();
 
-                Assert.False(true, "Should not have gotten here");
+                Assert.Fail("Should not have gotten here");
             }
             catch (InvalidOperationException)
             {
@@ -319,7 +319,7 @@ namespace Tests
             {
                 await xs.MoveNextAsync();
 
-                Assert.False(true, "Should not have gotten here");
+                Assert.Fail("Should not have gotten here");
             }
             catch (InvalidOperationException)
             {

+ 4 - 4
Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/Timeout.cs

@@ -23,7 +23,7 @@ namespace Tests
             {
                 await en.MoveNextAsync();
 
-                Assert.False(true, "MoveNextAsync should have thrown");
+                Assert.Fail("MoveNextAsync should have thrown");
             }
             catch (TimeoutException)
             {
@@ -48,7 +48,7 @@ namespace Tests
             {
                 await en.MoveNextAsync();
 
-                Assert.False(true, "MoveNextAsync should have thrown");
+                Assert.Fail("MoveNextAsync should have thrown");
             }
             catch (TimeoutException)
             {
@@ -77,7 +77,7 @@ namespace Tests
             {
                 await en.MoveNextAsync();
 
-                Assert.False(true, "MoveNextAsync should have thrown");
+                Assert.Fail("MoveNextAsync should have thrown");
             }
             catch (TimeoutException)
             {
@@ -115,7 +115,7 @@ namespace Tests
             {
                 await en.MoveNextAsync();
 
-                Assert.False(true, "MoveNextAsync should have thrown");
+                Assert.Fail("MoveNextAsync should have thrown");
             }
             catch (TimeoutException)
             {

+ 2 - 2
Ix.NET/Source/System.Interactive.Async.Tests/TaskExtTests.cs

@@ -22,7 +22,7 @@ namespace Tests
             }
             catch (AggregateException)
             {
-                Assert.True(false, "AggregateException has been thrown instead of InvalidOperationException");
+                Assert.Fail("AggregateException has been thrown instead of InvalidOperationException");
             }
             catch (InvalidOperationException)
             {
@@ -45,7 +45,7 @@ namespace Tests
             }
             catch (AggregateException)
             {
-                Assert.True(false, "AggregateException has been thrown instead of InvalidOperationException");
+                Assert.Fail("AggregateException has been thrown instead of InvalidOperationException");
             }
             catch (InvalidOperationException)
             {

+ 35 - 3
Ix.NET/Source/System.Interactive.Async/System.Interactive.Async.csproj

@@ -3,7 +3,16 @@
   <PropertyGroup>
     <Description>Interactive Extensions Async Library used to express queries over asynchronous enumerable sequences.</Description>
     <AssemblyTitle>Interactive Extensions - Async Library</AssemblyTitle>
-    <TargetFrameworks>net48;netstandard2.0;netstandard2.1;net6.0</TargetFrameworks>
+
+    <!--
+    .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.0;netstandard2.1;net10.0</TargetFrameworks>
     <PackageTags>Ix;Interactive;Extensions;Enumerable;Asynchronous</PackageTags>
   </PropertyGroup>
 
@@ -24,8 +33,31 @@
     <EmbeddedResource Include="Properties\System.Interactive.Async.rd.xml" />
   </ItemGroup>
 
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-rc.1.25451.107" />
+  </ItemGroup>
+
   <ItemGroup>
-    <ProjectReference Include="..\System.Linq.Async\System.Linq.Async.csproj" />
+    <ProjectReference Include="..\System.Linq.Async.SourceGenerator\System.Linq.Async.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" Private="false" />
   </ItemGroup>
-  
+
+  <ItemGroup>
+    <Compile Update="System\Linq\Operators\Average.Generated.cs">
+      <DependentUpon>Average.Generated.tt</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <None Update="System\Linq\Operators\Average.Generated.tt">
+      <LastGenOutput>Average.Generated.cs</LastGenOutput>
+      <Generator>TextTemplatingFileGenerator</Generator>
+    </None>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
+  </ItemGroup>
+
 </Project>

+ 52 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/IAsyncIListProvider.cs

@@ -0,0 +1,52 @@
+// 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
+{
+    /// <summary>
+    /// An iterator that can produce an array or <see cref="List{TElement}"/> through an optimized path.
+    /// </summary>
+    /// <remarks>
+    /// This interface is primarily used for internal purposes as an optimization for LINQ operators. Its use is discouraged.
+    /// It was made public because it was originally defined in the <c>System.Linq.Async</c> package but also used in
+    /// <c>System.Interactive.Async</c>. Now that <c>System.Linq.Async</c> is being retired in favor of .NET 10.0's
+    /// <c>System.Linq.AsyncEnumerable</c>, the <c>System.Interactive.Async</c> package no longer takes a dependency on
+    /// <c>System.Linq.Async</c>, which is why it now defines its own version of this interface here. We can't put a type
+    /// forwarder in <c>System.Interactive.Async</c> to here because that would risk creating a circular dependency in
+    /// cases where an application managed to get out-of-sync versions of the two packages, so this interface is not
+    /// backwards compatible with the old one. If you were implementing this in your own types to get the associated
+    /// optimizations, be aware that this is not supported, but implementing this copy of the interface (in place of
+    /// the old version defined in the deprecated <c>System.Linq.Async</c> package) will continue to provide the
+    /// same (unsupported) behaviour.
+    /// </remarks>
+    internal interface IAsyncIListProvider<TElement> : IAsyncEnumerable<TElement>
+    {
+        /// <summary>
+        /// Produce an array of the sequence through an optimized path.
+        /// </summary>
+        /// <param name="cancellationToken"></param>
+        /// <returns>The array.</returns>
+        ValueTask<TElement[]> ToArrayAsync(CancellationToken cancellationToken);
+
+        /// <summary>
+        /// Produce a <see cref="List{TElement}"/> of the sequence through an optimized path.
+        /// </summary>
+        /// <param name="cancellationToken"></param>
+        /// <returns>The <see cref="List{TElement}"/>.</returns>
+        ValueTask<List<TElement>> ToListAsync(CancellationToken cancellationToken);
+
+        /// <summary>
+        /// Returns the count of elements in the sequence.
+        /// </summary>
+        /// <param name="onlyIfCheap">If true then the count should only be calculated if doing
+        /// so is quick (sure or likely to be constant time), otherwise -1 should be returned.</param>
+        /// <param name="cancellationToken"></param>
+        /// <returns>The number of elements.</returns>
+        ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken);
+    }
+}

+ 26 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/AsAsyncEnumerable.cs

@@ -0,0 +1,26 @@
+// 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;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerableEx
+    {
+        // NB: Synchronous LINQ to Objects doesn't hide the implementation of the source either.
+
+        // Note: this was previously in System.Linq.Async, but since .NET 10.0's System.Linq.AsyncEnumerable chose not to
+        // implement it (even though Enumerable.AsEnumerable exists), we moved it into System.Interactive.Async so that
+        // it remains available even after developers remove their dependency on the deprecated System.Linq.Async.
+
+        /// <summary>
+        /// Hides the identity of an async-enumerable sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence whose identity to hide.</param>
+        /// <returns>An async-enumerable sequence that hides the identity of the source sequence.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        public static IAsyncEnumerable<TSource> AsAsyncEnumerable<TSource>(this IAsyncEnumerable<TSource> source) => source;
+    }
+}

+ 514 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Average.Generated.cs

@@ -0,0 +1,514 @@
+// 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>
+        /// Computes the average of an async-enumerable sequence of <see cref="int" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<double> Core(IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    if (!await e.MoveNextAsync())
+                    {
+                        throw Error.NoElements();
+                    }
+
+                    long sum = selector(e.Current);
+                    long count = 1;
+                    checked
+                    {
+                        while (await e.MoveNextAsync())
+                        {
+                            sum += selector(e.Current);
+                            ++count;
+                        }
+                    }
+
+                    return (double)sum / count;
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="long" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<double> Core(IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    if (!await e.MoveNextAsync())
+                    {
+                        throw Error.NoElements();
+                    }
+
+                    long sum = selector(e.Current);
+                    long count = 1;
+                    checked
+                    {
+                        while (await e.MoveNextAsync())
+                        {
+                            sum += selector(e.Current);
+                            ++count;
+                        }
+                    }
+
+                    return (double)sum / count;
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="float" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<float> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<float> Core(IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    if (!await e.MoveNextAsync())
+                    {
+                        throw Error.NoElements();
+                    }
+
+                    double sum = selector(e.Current);
+                    long count = 1;
+                    checked
+                    {
+                        while (await e.MoveNextAsync())
+                        {
+                            sum += selector(e.Current);
+                            ++count;
+                        }
+                    }
+
+                    return (float)(sum / count);
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="double" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<double> Core(IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    if (!await e.MoveNextAsync())
+                    {
+                        throw Error.NoElements();
+                    }
+
+                    double sum = selector(e.Current);
+                    long count = 1;
+                    checked
+                    {
+                        while (await e.MoveNextAsync())
+                        {
+                            sum += selector(e.Current);
+                            ++count;
+                        }
+                    }
+
+                    return sum / count;
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="decimal" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<decimal> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<decimal> Core(IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    if (!await e.MoveNextAsync())
+                    {
+                        throw Error.NoElements();
+                    }
+
+                    decimal sum = selector(e.Current);
+                    long count = 1;
+                    checked
+                    {
+                        while (await e.MoveNextAsync())
+                        {
+                            sum += selector(e.Current);
+                            ++count;
+                        }
+                    }
+
+                    return sum / count;
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Int}" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<double?> Core(IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    while (await e.MoveNextAsync())
+                    {
+                        var v = selector(e.Current);
+                        if (v.HasValue)
+                        {
+                            long sum = v.GetValueOrDefault();
+                            long count = 1;
+                            checked
+                            {
+                                while (await e.MoveNextAsync())
+                                {
+                                    v = selector(e.Current);
+                                    if (v.HasValue)
+                                    {
+                                        sum += v.GetValueOrDefault();
+                                        ++count;
+                                    }
+                                }
+                            }
+
+                            return (double)sum / count;
+                        }
+                    }
+                }
+
+                return null;
+            }
+        }
+
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Long}" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<double?> Core(IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    while (await e.MoveNextAsync())
+                    {
+                        var v = selector(e.Current);
+                        if (v.HasValue)
+                        {
+                            long sum = v.GetValueOrDefault();
+                            long count = 1;
+                            checked
+                            {
+                                while (await e.MoveNextAsync())
+                                {
+                                    v = selector(e.Current);
+                                    if (v.HasValue)
+                                    {
+                                        sum += v.GetValueOrDefault();
+                                        ++count;
+                                    }
+                                }
+                            }
+
+                            return (double)sum / count;
+                        }
+                    }
+                }
+
+                return null;
+            }
+        }
+
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Float}" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<float?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<float?> Core(IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    while (await e.MoveNextAsync())
+                    {
+                        var v = selector(e.Current);
+                        if (v.HasValue)
+                        {
+                            double sum = v.GetValueOrDefault();
+                            long count = 1;
+                            checked
+                            {
+                                while (await e.MoveNextAsync())
+                                {
+                                    v = selector(e.Current);
+                                    if (v.HasValue)
+                                    {
+                                        sum += v.GetValueOrDefault();
+                                        ++count;
+                                    }
+                                }
+                            }
+
+                            return (float)(sum / count);
+                        }
+                    }
+                }
+
+                return null;
+            }
+        }
+
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Double}" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<double?> Core(IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    while (await e.MoveNextAsync())
+                    {
+                        var v = selector(e.Current);
+                        if (v.HasValue)
+                        {
+                            double sum = v.GetValueOrDefault();
+                            long count = 1;
+                            checked
+                            {
+                                while (await e.MoveNextAsync())
+                                {
+                                    v = selector(e.Current);
+                                    if (v.HasValue)
+                                    {
+                                        sum += v.GetValueOrDefault();
+                                        ++count;
+                                    }
+                                }
+                            }
+
+                            return sum / count;
+                        }
+                    }
+                }
+
+                return null;
+            }
+        }
+
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Decimal}" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<decimal?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<decimal?> Core(IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
+            {
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    while (await e.MoveNextAsync())
+                    {
+                        var v = selector(e.Current);
+                        if (v.HasValue)
+                        {
+                            decimal sum = v.GetValueOrDefault();
+                            long count = 1;
+                            checked
+                            {
+                                while (await e.MoveNextAsync())
+                                {
+                                    v = selector(e.Current);
+                                    if (v.HasValue)
+                                    {
+                                        sum += v.GetValueOrDefault();
+                                        ++count;
+                                    }
+                                }
+                            }
+
+                            return sum / count;
+                        }
+                    }
+                }
+
+                return null;
+            }
+        }
+
+    }
+}

+ 155 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Average.Generated.tt

@@ -0,0 +1,155 @@
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+// 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
+{
+<#
+// Although .NET 10.0's System.Linq.AsyncEnumerable defines AverageAsync, it is missing some features that were previously defined in System.Linq.Async:
+//  Overloads of AverageAsync accepting a selector function (e.g. xs.AverageAsync(x => x.Value))
+//  The AverageAwaitAsync variants accepting an async selector function returning a ValueTask
+//  The AverageAwaitWithCancellationAsync variant where an async selector function accepts a CancellationToken
+// Since we are deprecating System.Linq.Async, these methods are now available there only in the runtime (lib) assemblies and not the
+// ref assemblies. So they are available for binary backwards compatibility, but are not visible during compilation. This is necessary
+// to ensure that code now gets the .NET 10 implementations of AverageAsync where available. But we want to enable code that was using
+// the functionality that .NET 10 did not replicate to be able to continue to work after removing the reference to System.Linq.Async.
+// So we've moved the relevant functionality back into System.Interactive.Async because that has always been the home of LINQ-like
+// features for IAsyncEnumerable<T> that aren't part of the core LINQ functionality.
+#>
+    public static partial class AsyncEnumerableEx
+    {
+<#
+var os = new[]
+{
+    new { type = "int", res = "double", sum = "long" },
+    new { type = "long", res = "double", sum = "long" },
+    new { type = "float", res = "float", sum = "double" },
+    new { type = "double", res = "double", sum = "double" },
+    new { type = "decimal", res = "decimal", sum = "decimal" },
+    new { type = "int?", res = "double?", sum = "long" },
+    new { type = "long?", res = "double?", sum = "long" },
+    new { type = "float?", res = "float?", sum = "double" },
+    new { type = "double?", res = "double?", sum = "double" },
+    new { type = "decimal?", res = "decimal?", sum = "decimal" },
+};
+
+foreach (var o in os)
+{
+    var isNullable = o.type.EndsWith("?");
+    var t = o.type.TrimEnd('?');
+
+    string res = "";
+
+    if (t == "int" || t == "long")
+        res = "(double)sum / count";
+    else if (t == "double" || t == "decimal")
+        res = "sum / count";
+    else if (t == "float")
+        res = "(float)(sum / count)";
+
+    var typeStr = o.type;
+    if (isNullable) {
+        typeStr = "Nullable{" + o.type.Substring(0, 1).ToUpper() + o.type.Substring(1, o.type.Length - 2) + "}";
+    }
+#>
+
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="<#=typeStr#>" /> values that are obtained by invoking a transform function on each element of the input sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">A sequence of values to calculate the average of.</param>
+        /// <param name="selector">A transform function to apply to each element.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>An async-enumerable sequence containing a single element with the average of the sequence of values, or null if the source sequence is empty or contains only values that are null.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
+        /// <exception cref="InvalidOperationException">(Asynchronous) The source sequence is empty.</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<<#=o.res#>> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, <#=o.type#>> selector, CancellationToken cancellationToken = default)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (selector == null)
+                throw Error.ArgumentNull(nameof(selector));
+
+            return Core(source, selector, cancellationToken);
+
+            static async ValueTask<<#=o.res#>> Core(IAsyncEnumerable<TSource> source, Func<TSource, <#=o.type#>> selector, CancellationToken cancellationToken)
+            {
+<#
+if (isNullable)
+{
+#>
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    while (await e.MoveNextAsync())
+                    {
+                        var v = selector(e.Current);
+                        if (v.HasValue)
+                        {
+                            <#=o.sum#> sum = v.GetValueOrDefault();
+                            long count = 1;
+                            checked
+                            {
+                                while (await e.MoveNextAsync())
+                                {
+                                    v = selector(e.Current);
+                                    if (v.HasValue)
+                                    {
+                                        sum += v.GetValueOrDefault();
+                                        ++count;
+                                    }
+                                }
+                            }
+
+                            return <#=res#>;
+                        }
+                    }
+                }
+
+                return null;
+<#
+}
+else
+{
+#>
+                await using (var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false))
+                {
+                    if (!await e.MoveNextAsync())
+                    {
+                        throw Error.NoElements();
+                    }
+
+                    <#=o.sum#> sum = selector(e.Current);
+                    long count = 1;
+                    checked
+                    {
+                        while (await e.MoveNextAsync())
+                        {
+                            sum += selector(e.Current);
+                            ++count;
+                        }
+                    }
+
+                    return <#=res#>;
+                }
+<#
+}
+#>
+            }
+        }
+
+<#
+}
+#>
+    }
+}

+ 23 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Disposables.cs

@@ -0,0 +1,23 @@
+// 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.Threading;
+
+namespace System.Linq
+{
+    internal sealed class CancellationTokenDisposable : IDisposable
+    {
+        private readonly CancellationTokenSource _cts = new();
+
+        public CancellationToken Token => _cts.Token;
+
+        public void Dispose()
+        {
+            if (!_cts.IsCancellationRequested)
+            {
+                _cts.Cancel();
+            }
+        }
+    }
+}

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

@@ -16,7 +16,7 @@ namespace System.Linq
 
         /// <summary>
         /// Applies an accumulator function over an async-enumerable sequence and returns each intermediate result.
-        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource}"/>.
+        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource}(IAsyncEnumerable{TSource}, Func{TSource, TSource, TSource}, CancellationToken)"/>.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence and the result of the aggregation.</typeparam>
         /// <param name="source">An async-enumerable sequence to accumulate over.</param>
@@ -54,7 +54,7 @@ namespace System.Linq
 
         /// <summary>
         /// Applies an accumulator function over an async-enumerable sequence and returns each intermediate result. The specified seed value is used as the initial accumulator value.
-        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource, Accumulate}"/>.
+        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource, TAccumulate}(IAsyncEnumerable{TSource}, TAccumulate, Func{TAccumulate, TSource, TAccumulate}, CancellationToken)"/>.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <typeparam name="TAccumulate">The type of the result of the aggregation.</typeparam>
@@ -87,7 +87,7 @@ namespace System.Linq
 
         /// <summary>
         /// Applies an asynchronous accumulator function over an async-enumerable sequence and returns each intermediate result.
-        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource}"/>.
+        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource}(IAsyncEnumerable{TSource}, Func{TSource, TSource, CancellationToken, ValueTask{TSource}}, CancellationToken)"/>.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence and the result of the aggregation.</typeparam>
         /// <param name="source">An async-enumerable sequence to accumulate over.</param>
@@ -126,7 +126,7 @@ namespace System.Linq
 #if !NO_DEEP_CANCELLATION
         /// <summary>
         /// Applies an asynchronous (cancellable) accumulator function over an async-enumerable sequence and returns each intermediate result.
-        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource}"/>.
+        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource, TAccumulate}(IAsyncEnumerable{TSource}, TAccumulate, Func{TAccumulate, TSource, CancellationToken, ValueTask{TAccumulate}}, CancellationToken)"/>.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence and the result of the aggregation.</typeparam>
         /// <param name="source">An async-enumerable sequence to accumulate over.</param>
@@ -165,7 +165,7 @@ namespace System.Linq
 
         /// <summary>
         /// Applies an asynchronous accumulator function over an async-enumerable sequence and returns each intermediate result. The specified seed value is used as the initial accumulator value.
-        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource, Accumulate}"/>.
+        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource, TAccumulate, TResult}(IAsyncEnumerable{TSource}, TAccumulate, Func{TAccumulate, TSource, CancellationToken, ValueTask{TAccumulate}}, Func{TAccumulate, CancellationToken, ValueTask{TResult}}, CancellationToken)"/>.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <typeparam name="TAccumulate">The type of the result of the aggregation.</typeparam>
@@ -199,7 +199,7 @@ namespace System.Linq
 #if !NO_DEEP_CANCELLATION
         /// <summary>
         /// Applies an asynchronous (cancellable) accumulator function over an async-enumerable sequence and returns each intermediate result. The specified seed value is used as the initial accumulator value.
-        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource, Accumulate}"/>.
+        /// For aggregation behavior with no intermediate results, see <see cref="AsyncEnumerable.AggregateAsync{TSource, TAccumulate, TResult}(IAsyncEnumerable{TSource}, TAccumulate, Func{TAccumulate, TSource, CancellationToken, ValueTask{TAccumulate}}, Func{TAccumulate, CancellationToken, ValueTask{TResult}}, CancellationToken)"/>.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <typeparam name="TAccumulate">The type of the result of the aggregation.</typeparam>

+ 222 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/ToAsyncEnumerable.Observable.cs

@@ -0,0 +1,222 @@
+// 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.Concurrent;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerableEx
+    {
+        /// <summary>
+        /// Converts an observable sequence to an async-enumerable sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">Observable sequence to convert to an async-enumerable sequence.</param>
+        /// <returns>The async-enumerable sequence whose elements are pulled from the given observable sequence.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this IObservable<TSource> source)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+
+            return new ObservableAsyncEnumerable<TSource>(source);
+        }
+
+        private sealed class ObservableAsyncEnumerable<TSource> : AsyncIterator<TSource>, IObserver<TSource>
+        {
+            private readonly IObservable<TSource> _source;
+
+            private ConcurrentQueue<TSource>? _values = new();
+            private Exception? _error;
+            private bool _completed;
+            private TaskCompletionSource<bool>? _signal;
+            private IDisposable? _subscription;
+            private CancellationTokenRegistration _ctr;
+
+            public ObservableAsyncEnumerable(IObservable<TSource> source) => _source = source;
+
+            public override AsyncIteratorBase<TSource> Clone() => new ObservableAsyncEnumerable<TSource>(_source);
+
+            public override ValueTask DisposeAsync()
+            {
+                Dispose();
+
+                return base.DisposeAsync();
+            }
+
+            protected override async ValueTask<bool> MoveNextCore()
+            {
+                //
+                // REVIEW: How often should we check? At the very least, we want to prevent
+                //         subscribing if cancellation is requested. A case may be made to
+                //         check for each iteration, namely because this operator is a bridge
+                //         with another interface. However, we also wire up cancellation to
+                //         the observable subscription, so there's redundancy here.
+                //
+                _cancellationToken.ThrowIfCancellationRequested();
+
+                switch (_state)
+                {
+                    case AsyncIteratorState.Allocated:
+                        //
+                        // NB: Breaking change to align with lazy nature of async iterators.
+                        //
+                        //     In previous implementations, the Subscribe call happened during
+                        //     the call to GetAsyncEnumerator.
+                        //
+                        // REVIEW: Confirm this design point. This implementation is compatible
+                        //         with an async iterator using "yield return", e.g. subscribing
+                        //         to the observable sequence and yielding values out of a local
+                        //         queue filled by observer callbacks. However, it departs from
+                        //         the dual treatment of Subscribe/GetEnumerator.
+                        //
+
+                        _subscription = _source.Subscribe(this);
+                        _ctr = _cancellationToken.Register(OnCanceled, state: null);
+                        _state = AsyncIteratorState.Iterating;
+                        goto case AsyncIteratorState.Iterating;
+
+                    case AsyncIteratorState.Iterating:
+                        while (true)
+                        {
+                            var completed = Volatile.Read(ref _completed);
+
+                            if (_values!.TryDequeue(out _current!))
+                            {
+                                return true;
+                            }
+                            else if (completed)
+                            {
+                                var error = _error;
+
+                                if (error != null)
+                                {
+                                    throw error;
+                                }
+
+                                return false;
+                            }
+
+                            await Resume().ConfigureAwait(false);
+                            Volatile.Write(ref _signal, null);
+                        }
+                }
+
+                await DisposeAsync().ConfigureAwait(false);
+                return false;
+            }
+
+            public void OnCompleted()
+            {
+                Volatile.Write(ref _completed, true);
+
+                DisposeSubscription();
+                OnNotification();
+            }
+
+            public void OnError(Exception error)
+            {
+                _error = error;
+                Volatile.Write(ref _completed, true);
+
+                DisposeSubscription();
+                OnNotification();
+            }
+
+            public void OnNext(TSource value)
+            {
+                _values?.Enqueue(value);
+
+                OnNotification();
+            }
+
+            private void OnNotification()
+            {
+                while (true)
+                {
+                    var signal = Volatile.Read(ref _signal);
+
+                    if (signal == TaskExt.True)
+                    {
+                        return;
+                    }
+
+                    if (signal != null)
+                    {
+                        signal.TrySetResult(true);
+                        return;
+                    }
+
+                    if (Interlocked.CompareExchange(ref _signal, TaskExt.True, null) == null)
+                    {
+                        return;
+                    }
+                }
+            }
+
+            private void Dispose()
+            {
+                _ctr.Dispose();
+                DisposeSubscription();
+
+                _values = null;
+                _error = null;
+            }
+
+            private void DisposeSubscription() => Interlocked.Exchange(ref _subscription, null)?.Dispose();
+
+            private void OnCanceled(object? state)
+            {
+                var cancelledTcs = default(TaskCompletionSource<bool>);
+
+                Dispose();
+
+                while (true)
+                {
+                    var signal = Volatile.Read(ref _signal);
+
+                    if (signal != null)
+                    {
+                        if (signal.TrySetCanceled(_cancellationToken))
+                            return;
+                    }
+
+                    if (cancelledTcs == null)
+                    {
+                        cancelledTcs = new TaskCompletionSource<bool>();
+                        cancelledTcs.TrySetCanceled(_cancellationToken);
+                    }
+
+                    if (Interlocked.CompareExchange(ref _signal, cancelledTcs, signal) == signal)
+                        return;
+                }
+            }
+
+            private Task Resume()
+            {
+                TaskCompletionSource<bool>? newSignal = null;
+
+                while (true)
+                {
+                    var signal = Volatile.Read(ref _signal);
+
+                    if (signal != null)
+                    {
+                        return signal.Task;
+                    }
+
+                    newSignal ??= new TaskCompletionSource<bool>();
+
+                    if (Interlocked.CompareExchange(ref _signal, newSignal, null) == null)
+                    {
+                        return newSignal.Task;
+                    }
+                }
+            }
+        }
+    }
+}

+ 48 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/ToAsyncEnumerable.Task.cs

@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT License.
+// See the LICENSE file in the project root for more information. 
+
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerableEx
+    {
+        /// <summary>
+        /// Converts a task to an async-enumerable sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source task.</typeparam>
+        /// <param name="task">Task to convert to an async-enumerable sequence.</param>
+        /// <returns>The async-enumerable sequence whose element is pulled from the given task.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="task"/> is null.</exception>
+        public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this Task<TSource> task)
+        {
+            if (task == null)
+                throw Error.ArgumentNull(nameof(task));
+
+            return new TaskToAsyncEnumerable<TSource>(task);
+        }
+
+        private sealed class TaskToAsyncEnumerable<T> : AsyncIterator<T>
+        {
+            private readonly Task<T> _task;
+
+            public TaskToAsyncEnumerable(Task<T> task) => _task = task;
+
+            public override AsyncIteratorBase<T> Clone() => new TaskToAsyncEnumerable<T>(_task);
+
+            protected override async ValueTask<bool> MoveNextCore()
+            {
+                if (_state == AsyncIteratorState.Allocated)
+                {
+                    _state = AsyncIteratorState.Iterating;
+                    _current = await _task.ConfigureAwait(false);
+                    return true;
+                }
+
+                return false;
+            }
+        }
+    }
+}

+ 83 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/ToObservable.cs

@@ -0,0 +1,83 @@
+// 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;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerableEx
+    {
+        /// <summary>
+        /// Converts an async-enumerable sequence to an observable sequence.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
+        /// <param name="source">Enumerable sequence to convert to an observable sequence.</param>
+        /// <returns>The observable sequence whose elements are pulled from the given enumerable sequence.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
+        public static IObservable<TSource> ToObservable<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+
+            return new ToObservableObservable<TSource>(source);
+        }
+
+        private sealed class ToObservableObservable<T> : IObservable<T>
+        {
+            private readonly IAsyncEnumerable<T> _source;
+
+            public ToObservableObservable(IAsyncEnumerable<T> source)
+            {
+                _source = source;
+            }
+
+            public IDisposable Subscribe(IObserver<T> observer)
+            {
+                var ctd = new CancellationTokenDisposable();
+
+                async void Core()
+                {
+                    await using var e = _source.GetAsyncEnumerator(ctd.Token);
+                    do
+                    {
+                        bool hasNext;
+                        var value = default(T)!;
+
+                        try
+                        {
+                            hasNext = await e.MoveNextAsync().ConfigureAwait(false);
+                            if (hasNext)
+                            {
+                                value = e.Current;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            if (!ctd.Token.IsCancellationRequested)
+                            {
+                                observer.OnError(ex);
+                            }
+
+                            return;
+                        }
+
+                        if (!hasNext)
+                        {
+                            observer.OnCompleted();
+                            return;
+                        }
+
+                        observer.OnNext(value);
+                    }
+                    while (!ctd.Token.IsCancellationRequested);
+                }
+
+                // Fire and forget
+                Core();
+
+                return ctd;
+            }
+        }
+    }
+}

+ 7 - 0
Ix.NET/Source/System.Interactive.Async/TaskExt.cs

@@ -11,6 +11,13 @@ namespace System.Threading.Tasks
     internal static class TaskExt
     {
         public static readonly Task<bool> Never = new TaskCompletionSource<bool>().Task;
+        public static readonly TaskCompletionSource<bool> True;
+
+        static TaskExt()
+        {
+            True = new TaskCompletionSource<bool>();
+            True.SetResult(true);
+        }
 
 #if USE_FAIR_AND_CHEAPER_MERGE
         public static WhenAnyValueTask<T> WhenAny<T>(ValueTask<T>[] tasks)

+ 2 - 4
Ix.NET/Source/System.Interactive.Providers/System.Interactive.Providers.csproj

@@ -3,7 +3,7 @@
   <PropertyGroup>
     <Description>Interactive Extensions Providers Library used to build query providers and express queries over enumerable sequences.</Description>
     <AssemblyTitle>Interactive Extensions - Providers Library</AssemblyTitle>
-    <TargetFrameworks>net48;netstandard2.0;net6.0</TargetFrameworks>
+    <TargetFrameworks>net48;netstandard2.0;net8.0</TargetFrameworks>
     <PackageTags>Ix;Interactive;Extensions;Enumerable</PackageTags>
   </PropertyGroup>
 
@@ -21,9 +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)/$(TargetFramework)/**" PackagePath="ref/$(TargetFramework)" Pack="true" />
   </ItemGroup>
 
   <!--

+ 7 - 4
Ix.NET/Source/System.Interactive.Tests/System.Interactive.Tests.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net8.0;net6.0</TargetFrameworks>
+    <TargetFrameworks>net48;net10.0;net8.0</TargetFrameworks>
 
     <!--
       CA1822: Make member static. Not necessary for test code.
@@ -21,10 +21,13 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
     <PackageReference Include="FluentAssertions" Version="6.4.0" />
-    <PackageReference Include="xunit" Version="2.4.1" />
+    <PackageReference Include="xunit" Version="2.9.3" />
   </ItemGroup>
 
 </Project>

+ 2 - 4
Ix.NET/Source/System.Interactive/System.Interactive.csproj

@@ -4,7 +4,7 @@
     <Description>Interactive Extensions Main Library used to express queries over enumerable sequences.</Description>
     <AssemblyTitle>Interactive Extensions - Main Library</AssemblyTitle>
     <Authors>Microsoft</Authors>
-    <TargetFrameworks>net48;netstandard2.0;net6.0</TargetFrameworks>
+    <TargetFrameworks>net48;netstandard2.0;net8.0</TargetFrameworks>
     <PackageTags>Ix;Interactive;Extensions;Enumerable</PackageTags>
   </PropertyGroup>
 
@@ -18,9 +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)/$(TargetFramework)/**" PackagePath="ref/$(TargetFramework)" Pack="true" />
   </ItemGroup>
 
   <!--

+ 25 - 4
Ix.NET/Source/System.Linq.Async.Queryable.Tests/System.Linq.Async.Queryable.Tests.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net8.0;net6.0</TargetFrameworks>
+    <TargetFrameworks>net48;net10.0;net8.0</TargetFrameworks>
     <NoWarn>$(NoWarn);CS0618</NoWarn>
   </PropertyGroup>
 
@@ -16,11 +16,32 @@
     <ProjectReference Include="..\System.Linq.Async.Queryable\System.Linq.Async.Queryable.csproj" />
   </ItemGroup>
 
+  <!--
+  Since this tests the legacy System.Linq.Async.Queryable package, we need prevent the compiler from using the .NET runtime library
+  System.Linq.AsyncEnumerable package.
+  So although we get this references transitively (or automatically on .NET 10.0+) we need to put them explicitly here to set aliases.
+  -->
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-rc.1.25451.107" Aliases="SystemLinqAsyncEnumerable" />
+  </ItemGroup>
+
+  <Target Name="_SetAliasOnBuiltInSystemLinqAsyncEnumerable" BeforeTargets="ResolveAssemblyReferences">
+
+    <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
+      <Reference Condition="'%(Reference.AssemblyName)' == 'System.Linq.AsyncEnumerable'">
+        <Aliases>SystemLinqAsyncEnumerable</Aliases>
+      </Reference>
+    </ItemGroup>
+  </Target>
+
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
     <PackageReference Include="FluentAssertions" Version="6.4.0" />
-    <PackageReference Include="xunit" Version="2.4.1" />
+    <PackageReference Include="xunit" Version="2.9.3" />
   </ItemGroup>
 
   <ItemGroup>

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

@@ -1,7 +1,15 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;netstandard2.0;netstandard2.1;net6.0</TargetFrameworks>
+    <!--
+    .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.0;netstandard2.1;net10.0</TargetFrameworks>
     <Title>System.Linq.Async.Queryable</Title>
     <PackageTags>LINQ;async;streams;query;provider</PackageTags>
     <Description>Provides support for Language-Integrated Query (LINQ) over IAsyncQueryable&lt;T&gt; sequences with query providers.</Description>
@@ -11,6 +19,20 @@
     <ProjectReference Include="..\System.Linq.Async\System.Linq.Async.csproj" />
   </ItemGroup>
 
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <!-- Although we get this transitively from System.Linq.Async, we need the alias to ensure we compile against the legacy System.Linq.Async -->
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-rc.1.25451.107"
+                      Aliases="SystemLinqAsyncEnumerable" />
+  </ItemGroup>
+  <Target Name="_SetAliasOnBuiltInSystemLinqAsyncEnumerable" BeforeTargets="ResolveAssemblyReferences">
+
+    <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
+      <Reference Condition="'%(Reference.AssemblyName)' == 'System.Linq.AsyncEnumerable'">
+        <Aliases>SystemLinqAsyncEnumerable</Aliases>
+      </Reference>
+    </ItemGroup>
+  </Target>
+
   <ItemGroup>
     <Compile Update="System\Linq\AsyncQueryable.Generated.cs">
       <DependentUpon>AsyncQueryable.Generated.tt</DependentUpon>

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

@@ -33,12 +33,13 @@ namespace System.Linq.Async.SourceGenerator
             if (context.SyntaxReceiver is not SyntaxReceiver syntaxReceiver) return;
 
             var options = GetGenerationOptions(context);
+            var attributeSymbol = GetAsyncOverloadAttributeSymbol(context);
             var methodsBySyntaxTree = GetMethodsGroupedBySyntaxTree(context, syntaxReceiver);
 
             foreach (var grouping in methodsBySyntaxTree)
                 context.AddSource(
                     $"{Path.GetFileNameWithoutExtension(grouping.SyntaxTree.FilePath)}.AsyncOverloads",
-                    GenerateOverloads(grouping, options));
+                    GenerateOverloads(grouping, options, context, attributeSymbol));
         }
 
         private static GenerationOptions GetGenerationOptions(GeneratorExecutionContext context)
@@ -50,22 +51,33 @@ namespace System.Linq.Async.SourceGenerator
                 syntaxReceiver,
                 GetAsyncOverloadAttributeSymbol(context));
 
-        private static string GenerateOverloads(AsyncMethodGrouping grouping, GenerationOptions options)
+        private static string GenerateOverloads(AsyncMethodGrouping grouping, GenerationOptions options, GeneratorExecutionContext context, INamedTypeSymbol attributeSymbol)
         {
             var usings = grouping.SyntaxTree.GetRoot() is CompilationUnitSyntax compilationUnit
                 ? compilationUnit.Usings.ToString()
                 : string.Empty;
 
+            // This source generator gets used not just in System.Linq.Async, but also for code that has migrated from
+            // System.Linq.Async to System.Interactive.Async. (E.g., we define overloads of AverageAsync that accept
+            // selector callbacks. The .NET runtime library implementation offers no equivalents. We want to continue
+            // to offer these even though we're decprecating System.Linq.Async, so they migrate into
+            // System.Interactive.Async.) In those cases, the containing type is typically AsyncEnumerableEx,
+            // but in System.Linq.Async it is AsyncEnumerable. So we need to discover the containing type name.
+            var containingTypeName = grouping.Methods.FirstOrDefault()?.Symbol.ContainingType.Name ?? "AsyncEnumerable";
+
             var overloads = new StringBuilder();
             overloads.AppendLine("#nullable enable");
             overloads.AppendLine(usings);
             overloads.AppendLine("namespace System.Linq");
             overloads.AppendLine("{");
-            overloads.AppendLine("    partial class AsyncEnumerable");
+            overloads.AppendLine($"    partial class {containingTypeName}");
             overloads.AppendLine("    {");
 
             foreach (var method in grouping.Methods)
-                overloads.AppendLine(GenerateOverload(method, options));
+            {
+                var model = context.Compilation.GetSemanticModel(method.Syntax.SyntaxTree);
+                overloads.AppendLine(GenerateOverload(method, options, model, attributeSymbol));
+            }
 
             overloads.AppendLine("    }");
             overloads.AppendLine("}");
@@ -73,8 +85,18 @@ namespace System.Linq.Async.SourceGenerator
             return overloads.ToString();
         }
 
-        private static string GenerateOverload(AsyncMethod method, GenerationOptions options)
-            => MethodDeclaration(method.Syntax.ReturnType, GetMethodName(method.Symbol, options))
+        private static string GenerateOverload(AsyncMethod method, GenerationOptions options, SemanticModel model, INamedTypeSymbol attributeSymbol)
+        {
+            var attributeListsWithGenerateAsyncOverloadRemoved = SyntaxFactory.List(method.Syntax.AttributeLists
+                .Select(list => AttributeList(SeparatedList(
+                        (from a in list.Attributes
+                         let am = model.GetSymbolInfo(a.Name).Symbol?.ContainingType
+                         where !SymbolEqualityComparer.Default.Equals(am, attributeSymbol)
+                         select a))))
+                .Where(list => list.Attributes.Count > 0));
+
+            return MethodDeclaration(method.Syntax.ReturnType, GetMethodName(method.Symbol, options))
+                .WithAttributeLists(attributeListsWithGenerateAsyncOverloadRemoved)
                 .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword)))
                 .WithTypeParameterList(method.Syntax.TypeParameterList)
                 .WithParameterList(method.Syntax.ParameterList)
@@ -87,9 +109,10 @@ namespace System.Linq.Async.SourceGenerator
                                 method.Syntax.ParameterList.Parameters
                                     .Select(p => Argument(IdentifierName(p.Identifier))))))))
                 .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
-                .WithLeadingTrivia(method.Syntax.GetLeadingTrivia().Where(t => t.GetStructure() is not DirectiveTriviaSyntax))
+                .WithLeadingTrivia(method.Syntax.GetLeadingTrivia().Where(t => !t.IsKind(SyntaxKind.DisabledTextTrivia) && t.GetStructure() is not DirectiveTriviaSyntax))
                 .NormalizeWhitespace()
                 .ToFullString();
+        }
 
         private static INamedTypeSymbol GetAsyncOverloadAttributeSymbol(GeneratorExecutionContext context)
             => context.Compilation.GetTypeByMetadataName("System.Linq.GenerateAsyncOverloadAttribute") ?? throw new InvalidOperationException();

+ 12 - 0
Ix.NET/Source/System.Linq.Async.SourceGenerator/Properties/launchSettings.json

@@ -0,0 +1,12 @@
+{
+  "profiles": {
+    "System.Linq.Async": {
+      "commandName": "DebugRoslynComponent",
+      "targetProject": "..\\System.Linq.Async\\System.Linq.Async.csproj"
+    },
+    "System.Interactive.Async": {
+      "commandName": "DebugRoslynComponent",
+      "targetProject": "..\\System.Interactive.Async\\System.Interactive.Async.csproj"
+    }
+  }
+}

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

@@ -1,6 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
+    <IsRoslynComponent>true</IsRoslynComponent>
     <LangVersion>9.0</LangVersion>
     <IsPackable>false</IsPackable>
   </PropertyGroup>

+ 39 - 4
Ix.NET/Source/System.Linq.Async.Tests/System.Linq.Async.Tests.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net8.0;net6.0</TargetFrameworks>
+    <TargetFrameworks>net48;net10.0;net8.0</TargetFrameworks>
 
     <!--
     CA1510: Use ArgumentNullException.ThrowIfNull - not available on .NET 4.8
@@ -41,14 +41,49 @@
   </ItemGroup>
 
   <ItemGroup>
+    <!--
+    System.Linq.Async brings in a transitive dependency on System.Interactive.Async, because in normal use,
+    the methods in System.Linq.Async that are not in System.Linq.AsyncEnumerable are now used via their new
+    home in System.Interactive.Async. However, there's a complication: for binary compatibility we retain these
+    methods in the System.Linq.Async runtime assemblies (lib), removing them from the ref assemblies so that
+    they are invisible at compile time. However, that trick works only for references via the NuGet package; this
+    test project has a direct project reference to System.Linq.Async meaning that it can see all the methods that
+    are deliberately hidden at compile time in normal use. This particular test project actually wants to test
+    those hidden methods (because we still need to ensure that code relying on the binary compatibility will work).
+    So we set an alias on System.Interactive.Async to avoid picking up its extension methods unless we explicitly want to.
+    -->
+    <ProjectReference Include="..\System.Interactive.Async\System.Interactive.Async.csproj">
+      <Aliases>SystemInteractiveAsync</Aliases>
+    </ProjectReference>
     <ProjectReference Include="..\System.Linq.Async\System.Linq.Async.csproj" />
   </ItemGroup>
 
+  <!--
+  Since this tests the legacy System.Linq.Async package, we need prevent the compiler from using the .NET runtime library
+  System.Linq.AsyncEnumerable package.
+  So although we get this references transitively (or automatically on .NET 10.0+) we need to put them explicitly here to set aliases.
+  -->
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-rc.1.25451.107" Aliases="SystemLinqAsyncEnumerable" />
+  </ItemGroup>
+
+  <Target Name="_SetAliasOnBuiltInSystemLinqAsyncEnumerable" BeforeTargets="ResolveAssemblyReferences">
+
+    <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
+      <Reference Condition="'%(Reference.AssemblyName)' == 'System.Linq.AsyncEnumerable'">
+        <Aliases>SystemLinqAsyncEnumerable</Aliases>
+      </Reference>
+    </ItemGroup>
+  </Target>
+
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
     <PackageReference Include="FluentAssertions" Version="6.4.0" />
-    <PackageReference Include="xunit" Version="2.4.1" />
+    <PackageReference Include="xunit" Version="2.9.3" />
   </ItemGroup>
 
   <ItemGroup>

+ 3 - 2
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Range.cs

@@ -36,6 +36,7 @@ namespace Tests
         public async Task Range_Simple_IAsyncPartition()
         {
             var xs = AsyncEnumerable.Range(2, 5);
+            int[] expected = [2, 3, 4, 5, 6];
 
             Assert.Equal(5, await xs.CountAsync());
 
@@ -63,8 +64,8 @@ namespace Tests
             Assert.Equal(2, await xs.Take(1024).FirstAsync());
             Assert.Equal(6, await xs.Take(1024).LastAsync());
 
-            Assert.Equal([2, 3, 4, 5, 6], await xs.ToArrayAsync());
-            Assert.Equal(new[] { 2, 3, 4, 5, 6 }, await xs.ToListAsync());
+            Assert.Equal(expected, await xs.ToArrayAsync());
+            Assert.Equal(expected, await xs.ToListAsync());
         }
 
         [Fact]

+ 4 - 2
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Reverse.cs

@@ -67,8 +67,9 @@ namespace Tests
         {
             var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
             var ys = xs.Reverse();
+            int[] expected = [3, 2, 1];
 
-            Assert.Equal([3, 2, 1], await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
         }
 
         [Fact]
@@ -103,8 +104,9 @@ namespace Tests
         {
             var xs = new[] { 1, 2, 3 }.ToAsyncEnumerable();
             var ys = xs.Reverse().Prepend(4); // to trigger onlyIfCheap
+            int[] expected = [4, 3, 2, 1];
 
-            Assert.Equal([4, 3, 2, 1], await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
         }
     }
 }

+ 6 - 3
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Select.cs

@@ -277,8 +277,9 @@ namespace Tests
         {
             var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.Select(x => x * 2);
+            int[] expected = [2, 4, 6, 8, 10];
 
-            Assert.Equal([2, 4, 6, 8, 10], await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
         }
 
         [Fact]
@@ -544,8 +545,9 @@ namespace Tests
         {
             var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
+            int[] expected = [2, 4, 6, 8, 10];
 
-            Assert.Equal([2, 4, 6, 8, 10], await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
         }
 
 #if !NO_DEEP_CANCELLATION
@@ -813,8 +815,9 @@ namespace Tests
         {
             var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
+            int[] expected = [2, 4, 6, 8, 10];
 
-            Assert.Equal([2, 4, 6, 8, 10], await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
         }
 
 #endif

+ 18 - 12
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Skip.cs

@@ -114,6 +114,7 @@ namespace Tests
         {
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable().Where(x => true);
             var ys = xs.Skip(2);
+            int[] expected = [3, 4];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -123,8 +124,8 @@ namespace Tests
             Assert.Equal(3, await ys.ElementAtAsync(0));
             Assert.Equal(4, await ys.ElementAtAsync(1));
 
-            Assert.Equal([3, 4], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 3, 4 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -132,6 +133,7 @@ namespace Tests
         {
             var xs = new[] { -2, -1, 0, 1, 2, 3, 4 }.ToAsyncEnumerable().Where(x => true);
             var ys = xs.Skip(2).Skip(3);
+            int[] expected = [3, 4];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -141,8 +143,8 @@ namespace Tests
             Assert.Equal(3, await ys.ElementAtAsync(0));
             Assert.Equal(4, await ys.ElementAtAsync(1));
 
-            Assert.Equal([3, 4], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 3, 4 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -150,6 +152,7 @@ namespace Tests
         {
             var xs = new[] { 2, 3, 4, 5 }.ToAsyncEnumerable().Where(x => true);
             var ys = xs.Skip(1).Take(2);
+            int[] expected = [3, 4];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -159,8 +162,8 @@ namespace Tests
             Assert.Equal(3, await ys.ElementAtAsync(0));
             Assert.Equal(4, await ys.ElementAtAsync(1));
 
-            Assert.Equal([3, 4], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 3, 4 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -204,6 +207,7 @@ namespace Tests
         {
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
             var ys = xs.Skip(2);
+            int[] expected = [3, 4];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -213,8 +217,8 @@ namespace Tests
             Assert.Equal(3, await ys.ElementAtAsync(0));
             Assert.Equal(4, await ys.ElementAtAsync(1));
 
-            Assert.Equal([3, 4], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 3, 4 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -222,6 +226,7 @@ namespace Tests
         {
             var xs = new[] { -2, -1, 0, 1, 2, 3, 4 }.ToAsyncEnumerable();
             var ys = xs.Skip(2).Skip(3);
+            int[] expected = [3, 4];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -231,8 +236,8 @@ namespace Tests
             Assert.Equal(3, await ys.ElementAtAsync(0));
             Assert.Equal(4, await ys.ElementAtAsync(1));
 
-            Assert.Equal([3, 4], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 3, 4 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -240,6 +245,7 @@ namespace Tests
         {
             var xs = new[] { 2, 3, 4, 5 }.ToAsyncEnumerable();
             var ys = xs.Skip(1).Take(2);
+            int[] expected = [3, 4];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -249,8 +255,8 @@ namespace Tests
             Assert.Equal(3, await ys.ElementAtAsync(0));
             Assert.Equal(4, await ys.ElementAtAsync(1));
 
-            Assert.Equal([3, 4], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 3, 4 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]

+ 18 - 12
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Take.cs

@@ -134,6 +134,7 @@ namespace Tests
         {
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable().Where(x => true);
             var ys = xs.Take(2);
+            int[] expected = [1, 2];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -143,8 +144,8 @@ namespace Tests
             Assert.Equal(1, await ys.ElementAtAsync(0));
             Assert.Equal(2, await ys.ElementAtAsync(1));
 
-            Assert.Equal([1, 2], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 1, 2 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -152,6 +153,7 @@ namespace Tests
         {
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable().Where(x => true);
             var ys = xs.Take(3).Take(2);
+            int[] expected = [1, 2];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -161,8 +163,8 @@ namespace Tests
             Assert.Equal(1, await ys.ElementAtAsync(0));
             Assert.Equal(2, await ys.ElementAtAsync(1));
 
-            Assert.Equal([1, 2], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 1, 2 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -170,6 +172,7 @@ namespace Tests
         {
             var xs = new[] { 2, 3, 4, 5 }.ToAsyncEnumerable().Where(x => true);
             var ys = xs.Take(3).Skip(1);
+            int[] expected = [3, 4];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -179,8 +182,8 @@ namespace Tests
             Assert.Equal(3, await ys.ElementAtAsync(0));
             Assert.Equal(4, await ys.ElementAtAsync(1));
 
-            Assert.Equal([3, 4], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 3, 4 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -224,6 +227,7 @@ namespace Tests
         {
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
             var ys = xs.Take(2);
+            int[] expected = [1, 2];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -233,8 +237,8 @@ namespace Tests
             Assert.Equal(1, await ys.ElementAtAsync(0));
             Assert.Equal(2, await ys.ElementAtAsync(1));
 
-            Assert.Equal([1, 2], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 1, 2 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -242,6 +246,7 @@ namespace Tests
         {
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
             var ys = xs.Take(3).Take(2);
+            int[] expected = [1, 2];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -251,8 +256,8 @@ namespace Tests
             Assert.Equal(1, await ys.ElementAtAsync(0));
             Assert.Equal(2, await ys.ElementAtAsync(1));
 
-            Assert.Equal([1, 2], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 1, 2 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]
@@ -260,6 +265,7 @@ namespace Tests
         {
             var xs = new[] { 2, 3, 4, 5 }.ToAsyncEnumerable();
             var ys = xs.Take(3).Skip(1);
+            int[] expected = [3, 4];
 
             Assert.Equal(2, await ys.CountAsync());
 
@@ -269,8 +275,8 @@ namespace Tests
             Assert.Equal(3, await ys.ElementAtAsync(0));
             Assert.Equal(4, await ys.ElementAtAsync(1));
 
-            Assert.Equal([3, 4], await ys.ToArrayAsync());
-            Assert.Equal(new[] { 3, 4 }, await ys.ToListAsync());
+            Assert.Equal(expected, await ys.ToArrayAsync());
+            Assert.Equal(expected, await ys.ToListAsync());
         }
 
         [Fact]

+ 6 - 6
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ToAsyncEnumerable.cs

@@ -189,7 +189,7 @@ namespace Tests
             xc.CopyTo(arr, 0);
             Assert.True(arr.SequenceEqual(xc));
             xc.Clear();
-            Assert.Equal(0, xc.Count);
+            Assert.Empty(xc);
         }
 
         [Fact]
@@ -223,7 +223,7 @@ namespace Tests
             xl.CopyTo(arr, 0);
             Assert.True(arr.SequenceEqual(xl));
             xl.Clear();
-            Assert.Equal(0, xl.Count);
+            Assert.Empty(xl);
         }
 
         [Fact]
@@ -314,7 +314,7 @@ namespace Tests
             }
 
             await e.DisposeAsync();
-            stop.WaitOne();
+            await Task.Run(stop.WaitOne);
         }
 
         [Fact]
@@ -352,7 +352,7 @@ namespace Tests
             }
 
             await e.DisposeAsync();
-            stop.WaitOne();
+            await Task.Run(stop.WaitOne);
 
             Assert.Equal(2, subCount);
         }
@@ -390,7 +390,7 @@ namespace Tests
             }
 
             c.Cancel();
-            stop.WaitOne();
+            await Task.Run(stop.WaitOne);
         }
 
         [Fact]
@@ -453,7 +453,7 @@ namespace Tests
             }
 
             await e.DisposeAsync();
-            stop.WaitOne();
+            await Task.Run(stop.WaitOne);
         }
 
         // TODO: Add more tests for Observable conversion.

+ 2 - 2
Ix.NET/Source/System.Linq.Async.Tests/ValueTaskHelpers.cs

@@ -97,10 +97,10 @@ namespace Xunit
             }
 
             if (exception == null)
-                throw new ThrowsException(exceptionType);
+                throw ThrowsException.ForNoException(exceptionType);
 
             if (!exceptionType.Equals(exception.GetType()))
-                throw new ThrowsException(exceptionType, exception);
+                throw ThrowsException.ForIncorrectExceptionType(exceptionType, exception);
 
             return exception;
         }

+ 49 - 3
Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj

@@ -1,7 +1,15 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;netstandard2.0;netstandard2.1;net6.0</TargetFrameworks>
+    <!--
+    .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.0;netstandard2.1;net10.0</TargetFrameworks>
     <Title>System.Linq.Async</Title>    
     <PackageTags>LINQ;async;streams;query</PackageTags>
     <Description>Provides support for Language-Integrated Query (LINQ) over IAsyncEnumerable&lt;T&gt; sequences.</Description>  
@@ -16,6 +24,17 @@
           Pack="true" />
   </ItemGroup>
 
+  <PropertyGroup>
+    <!--
+    The ref assembly defines the public API visible at compile time, so it should not include any methods for which
+    System.Linq.AsyncEnumerable defines source-compatible replacements, because their continued availability would
+    cause compile-time ambiguity.
+    We retain the code because we continue to make these methods available in the runtime assembly (in the lib folder)
+    to provide binary compatibility. This project builds the runtime assembly, so we need to include these methods.
+    -->
+    <DefineConstants>$(DefineConstants);INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES</DefineConstants>
+  </PropertyGroup>
+
   <!--
   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.
@@ -27,8 +46,9 @@
     <!--
     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.
+    CS0618: Type or member is obsolete - this whole library is essentially obsolete, so internal use of obsolete features is OK and widespread.
     -->
-    <NoWarn>$(NoWarn);NU5128;NU5131</NoWarn>
+    <NoWarn>$(NoWarn);NU5128;NU5131;CS0618</NoWarn>
   </PropertyGroup>
 
   <PropertyGroup>
@@ -57,10 +77,32 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Condition="'$(TargetFramework)' == 'net48' or '$(TargetFramework)' == 'netstandard2.0' " Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
+    <!--
+    System.Linq.Async is being deprecated by System.Linq.AsyncEnumerable (part of .NET 10, but available to older runtimes via NuGet)
+    but System.Linq.AsyncEnumerable does not include all of System.Linq.Async's functionality. We're moving that functionality into
+    System.Interactive.Async, because that is the home of IAsyncEnumerable features that are LINQ-adjacent but not build into
+    the .NET runtime libraries.
+    By referencing System.Interactive.Async here, we make that functionality available to users of System.Linq.Async until such
+    time as they remove their reference to this library.
+    -->
+    <ProjectReference Include="..\System.Interactive.Async\System.Interactive.Async.csproj" Aliases="SystemInteractiveAsync" />
     <ProjectReference Include="..\System.Linq.Async.SourceGenerator\System.Linq.Async.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" Private="false" />
   </ItemGroup>
 
+
+  <ItemGroup Condition="'$(TargetFramework)' != 'net10.0'">
+    <PackageReference Include="System.Linq.AsyncEnumerable" Version="10.0.0-rc.1.25451.107" Aliases="SystemLinqAsyncEnumerable" />
+  </ItemGroup>
+
+  <Target Name="_SetAliasOnBuiltInSystemLinqAsyncEnumerable" BeforeTargets="ResolveAssemblyReferences">
+    
+    <ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
+      <Reference Condition="'%(Reference.AssemblyName)' == 'System.Linq.AsyncEnumerable'">
+        <Aliases>SystemLinqAsyncEnumerable</Aliases>
+      </Reference>
+    </ItemGroup>
+  </Target>
+
   <ItemGroup>
     <Compile Update="System\Linq\AsyncEnumerable.AsyncOverloads.cs">
       <DesignTime>True</DesignTime>
@@ -121,4 +163,8 @@
     </None>
   </ItemGroup>
 
+  <ItemGroup>
+    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
+  </ItemGroup>
+
 </Project>

+ 2 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/AsyncEnumerablePartition.cs

@@ -11,6 +11,7 @@ using System.Threading.Tasks;
 
 namespace System.Linq
 {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     /// <summary>
     /// An iterator that yields the items of part of an <see cref="IAsyncEnumerable{TSource}"/>.
     /// </summary>
@@ -379,4 +380,5 @@ namespace System.Linq
             return index;
         }
     }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 }

+ 2 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/AsyncListPartition.cs

@@ -11,6 +11,7 @@ using System.Threading.Tasks;
 
 namespace System.Linq
 {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     /// <summary>
     /// An iterator that yields the items of part of an <see cref="IList{TSource}"/>.
     /// </summary>
@@ -182,4 +183,5 @@ namespace System.Linq
             return new ValueTask<int>(Count);
         }
     }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 }

+ 6 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/IAsyncGrouping.cs

@@ -6,6 +6,12 @@ using System.Collections.Generic;
 
 namespace System.Linq
 {
+    // System.Linq.AsyncEnumerable defines no equivalent for this, because it uses an IAsyncEnumerable<IGrouping<TKey, TElement>>
+    // In theory that is less good because it allows await only at the per-group level. In practice System.Linq.Async never
+    // made use of that because the only operators that returned an IAsyncGrouping<TKey, TElement> fully enumerated the source
+    // on the very first MoveNextAsync, meaning that by the time you got to inspect a group, its contents were available
+    // immediately. So this interface merely forced code to use await foreach unnecessarily. We retain this for binary
+    // compatibility, but it serves no long term purpose.
     public interface IAsyncGrouping<out TKey, out TElement> : IAsyncEnumerable<TElement>
     {
         TKey Key { get; }

+ 9 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/IAsyncIListProvider.cs

@@ -11,6 +11,15 @@ namespace System.Linq
     /// <summary>
     /// An iterator that can produce an array or <see cref="List{TElement}"/> through an optimized path.
     /// </summary>
+    /// <remarks>
+    /// This interface is primarily used for internal purposes as an optimization for LINQ operators. It was made public because
+    /// it was defined in the <c>System.Linq.Async</c> package but also used in <c>System.Interactive.Async</c>. Now that
+    /// <c>System.Linq.Async</c> is being retired in favor of .NET 10.0's <c>System.Linq.AsyncEnumerable</c>, the
+    /// <c>System.Interactive.Async</c> package no longer takes a dependency on <c>System.Linq.Async</c>, and therefore defines
+    /// its own version of this interface. We can't replace this with a type forwarder here because that would risk creating a
+    /// circular dependency in cases where an application managed to get out-of-sync versions of the two packages.
+    /// </remarks>
+    [Obsolete("This interface was always unsupported, and the IAsyncEnumerable<T> LINQ implementation in System.Linq.AsyncEnumerable does not recognize it, so this no longer serves a purpose")]
     public interface IAsyncIListProvider<TElement> : IAsyncEnumerable<TElement>
     {
         /// <summary>

+ 2 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/IOrderedAsyncEnumerable.cs

@@ -8,6 +8,7 @@ using System.Threading.Tasks;
 
 namespace System.Linq
 {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     /// <summary>
     /// Represents a sorted async-enumerable sequence.
     /// </summary>
@@ -46,4 +47,5 @@ namespace System.Linq
         IOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, bool descending);
 #endif
     }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 }

+ 30 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Aggregate.cs

@@ -10,6 +10,10 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.aggregateasync?view=net-9.0-pp#system-linq-asyncenumerable-aggregateasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-0-0))-system-threading-cancellationtoken)
+
+
         /// <summary>
         /// Applies an accumulator function over an async-enumerable sequence, returning the result of the aggregation as a single element in the result sequence.
         /// For aggregation behavior with incremental intermediate results, see System.Interactive.Async.AsyncEnumerableEx.Scan{TSource}.
@@ -50,6 +54,7 @@ namespace System.Linq
                 return acc;
             }
         }
+#endif
 
         /// <summary>
         /// Applies an accumulator function over an async-enumerable sequence, returning the result of the aggregation as a single element in the result sequence.
@@ -63,6 +68,7 @@ namespace System.Linq
         /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use AggregateAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AggregateAwaitAsync now exists as overloads of AggregateAsync.")]
         private static ValueTask<TSource> AggregateAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, TSource, ValueTask<TSource>> accumulator, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -93,7 +99,16 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.aggregateasync?view=net-9.0-pp#system-linq-asyncenumerable-aggregateasync-3(system-collections-generic-iasyncenumerable((-0))-1-system-func((-1-0-system-threading-cancellationtoken-system-threading-tasks-valuetask((-1))))-system-func((-1-system-threading-cancellationtoken-system-threading-tasks-valuetask((-2))))-system-threading-cancellationtoken)
+        // public static ValueTask<TResult> AggregateAsync<TSource, TAccumulate, TResult>(
+        //  this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, ValueTask<TAccumulate>> func, Func<TAccumulate, CancellationToken, ValueTask<TResult>> resultSelector, CancellationToken cancellationToken = default);
+        // Corresponds to:
+        // public static ValueTask<TResult> AggregateAwaitWithCancellationAsync<TSource, TAccumulate, TResult>(
+        //  this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, ValueTask<TAccumulate>> accumulator, Func<TAccumulate, CancellationToken, ValueTask<TResult>> resultSelector, CancellationToken cancellationToken = default) { }
+
         [GenerateAsyncOverload]
+        [Obsolete("Use AggregateAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AggregateAwaitWithCancellationAsync functionality now exists as overloads of AggregateAsync.")]
         private static ValueTask<TSource> AggregateAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, TSource, CancellationToken, ValueTask<TSource>> accumulator, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -124,6 +139,11 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.aggregateasync?view=net-9.0-pp#system-linq-asyncenumerable-aggregateasync-2(system-collections-generic-iasyncenumerable((-0))-1-system-func((-1-0-1))-system-threading-cancellationtoken)
+        //public static ValueTask<TAccumulate> AggregateAsync<TSource, TAccumulate>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, CancellationToken cancellationToken = default);
+
         /// <summary>
         /// Applies an accumulator function over an async-enumerable sequence, returning the result of the aggregation as a single element in the result sequence. The specified seed value is used as the initial accumulator value.
         /// For aggregation behavior with incremental intermediate results, see System.Interactive.Async.AsyncEnumerableEx.Scan{TSource, Accumulate}".
@@ -158,6 +178,7 @@ namespace System.Linq
                 return acc;
             }
         }
+#endif
 
         /// <summary>
         /// Applies an accumulator function over an async-enumerable sequence, returning the result of the aggregation as a single element in the result sequence. The specified seed value is used as the initial accumulator value.
@@ -172,6 +193,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="accumulator"/> is <see langword="null"/>.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use AggregateAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AggregateAwaitAsync functionality now exists as overloads of AggregateAsync.")]
         private static ValueTask<TAccumulate> AggregateAwaitAsyncCore<TSource, TAccumulate>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, ValueTask<TAccumulate>> accumulator, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -196,6 +218,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use AggregateAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AggregateAwaitWithCancellationAsync functionality now exists as overloads of AggregateAsync.")]
         private static ValueTask<TAccumulate> AggregateAwaitWithCancellationAsyncCore<TSource, TAccumulate>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, ValueTask<TAccumulate>> accumulator, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -219,6 +242,10 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.aggregateasync?view=net-9.0-pp#system-linq-asyncenumerable-aggregateasync-3(system-collections-generic-iasyncenumerable((-0))-1-system-func((-1-0-1))-system-func((-1-2))-system-threading-cancellationtoken)
+        // public static ValueTask<TResult> AggregateAsync<TSource, TAccumulate, TResult>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken = default);
+
         /// <summary>
         /// Applies an accumulator function over an async-enumerable sequence, returning the result of the aggregation as a single element in the result sequence. The specified seed value is used as the initial accumulator value,
         /// and the specified result selector function is used to select the result value.
@@ -257,6 +284,7 @@ namespace System.Linq
                 return resultSelector(acc);
             }
         }
+#endif
 
         /// <summary>
         /// Applies an accumulator function over an async-enumerable sequence, returning the result of the aggregation as a single element in the result sequence. The specified seed value is used as the initial accumulator value,
@@ -273,6 +301,7 @@ namespace System.Linq
         /// <returns>A ValueTask containing the value obtained by applying the result selector to the final accumulator value.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="accumulator"/> or <paramref name="resultSelector"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use AggregateAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AggregateAwaitAsync functionality now exists as overloads of AggregateAsync.")]
         private static ValueTask<TResult> AggregateAwaitAsyncCore<TSource, TAccumulate, TResult>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, ValueTask<TAccumulate>> accumulator, Func<TAccumulate, ValueTask<TResult>> resultSelector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -299,6 +328,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use AggregateAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AggregateAwaitWithCancellationAsync functionality now exists as overloads of AggregateAsync.")]
         private static ValueTask<TResult> AggregateAwaitWithCancellationAsyncCore<TSource, TAccumulate, TResult>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, ValueTask<TAccumulate>> accumulator, Func<TAccumulate, CancellationToken, ValueTask<TResult>> resultSelector, CancellationToken cancellationToken = default)
         {
             if (source == null)

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

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.allasync?view=net-9.0-pp#system-linq-asyncenumerable-allasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Determines whether all elements of an async-enumerable sequence satisfy a condition.
         /// </summary>
@@ -42,6 +45,7 @@ namespace System.Linq
                 return true;
             }
         }
+#endif
 
         /// <summary>
         /// Determines whether all elements in an async-enumerable sequence satisfy a condition.
@@ -54,6 +58,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is <see langword="null"/>.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use AllAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AllAwaitAsync functionality now exists as overloads of All.")]
         private static ValueTask<bool> AllAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -79,6 +84,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use AllAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AllAwaitWithCancellationAsync functionality now exists as overloads of AllAsync.")]
         internal static ValueTask<bool> AllAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)

+ 7 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Any.cs

@@ -10,6 +10,8 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.anyasync?view=net-9.0-pp#system-linq-asyncenumerable-anyasync-1(system-collections-generic-iasyncenumerable((-0))-system-threading-cancellationtoken)
         /// <summary>
         /// Determines whether an async-enumerable sequence contains any elements.
         /// </summary>
@@ -34,6 +36,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.anyasync?view=net-9.0-pp#system-linq-asyncenumerable-anyasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Determines whether any element of an async-enumerable sequence satisfies a condition.
         /// </summary>
@@ -66,6 +70,7 @@ namespace System.Linq
                 return false;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Determines whether any element in an async-enumerable sequence satisfies a condition.
@@ -78,6 +83,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is <see langword="null"/>.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use AnyAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AnyAwaitAsync functionality now exists as overloads of AnyAsync.")]
         private static ValueTask<bool> AnyAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -103,6 +109,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use AnyAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the AnyAwaitWithCancellationAsync functionality now exists as overloads of AnyAsync.")]
         internal static ValueTask<bool> AnyAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)

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

@@ -12,6 +12,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.append?view=net-9.0-pp
+
         /// <summary>
         /// Append a value to an async-enumerable sequence.
         /// </summary>
@@ -33,6 +36,8 @@ namespace System.Linq
             return new AppendPrepend1AsyncIterator<TSource>(source, element, appending: true);
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.prepend?view=net-9.0-pp
+
         /// <summary>
         /// Prepend a value to an async-enumerable sequence.
         /// </summary>
@@ -53,6 +58,7 @@ namespace System.Linq
 
             return new AppendPrepend1AsyncIterator<TSource>(source, element, appending: false);
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         private abstract class AppendPrependAsyncIterator<TSource> : AsyncIterator<TSource>, IAsyncIListProvider<TSource>
         {

+ 8 - 1
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/AsAsyncEnumerable.cs

@@ -7,8 +7,14 @@ using System.Collections.Generic;
 namespace System.Linq
 {
     public static partial class AsyncEnumerable
-    {
         // NB: Synchronous LINQ to Objects doesn't hide the implementation of the source either.
+    {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // Note: this one isn't actually in the System.Linq.AsyncEnumerable package, so we've moved it
+        // to System.Interactive.Async because that's the home for LINQ-like implementations for
+        // IAsyncEnumerable<T> that aren't in the runtime libraries.
+        // It therefore remains available only for runtime binary compatibility, and is no longer
+        // visible in System.Linq.Async at compile time.
 
         /// <summary>
         /// Hides the identity of an async-enumerable sequence.
@@ -18,5 +24,6 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence that hides the identity of the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
         public static IAsyncEnumerable<TSource> AsAsyncEnumerable<TSource>(this IAsyncEnumerable<TSource> source) => source;
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 59 - 14
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Average.Generated.cs

@@ -10,6 +10,7 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="int" /> values.
         /// </summary>
@@ -94,6 +95,7 @@ namespace System.Linq
                 }
             }
         }
+#endif
 
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
@@ -107,6 +109,7 @@ namespace System.Linq
         /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -143,6 +146,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<int>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -178,6 +182,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="long" /> values.
         /// </summary>
@@ -262,9 +267,10 @@ namespace System.Linq
                 }
             }
         }
+#endif
 
         /// <summary>
-        /// Computes the average of an async-enumerable sequence of <see cref="long"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
         /// </summary>
         /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
         /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
@@ -275,6 +281,7 @@ namespace System.Linq
         /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -311,6 +318,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<long>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -346,6 +354,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="float" /> values.
         /// </summary>
@@ -430,9 +439,10 @@ namespace System.Linq
                 }
             }
         }
+#endif
 
         /// <summary>
-        /// Computes the average of an async-enumerable sequence of <see cref="float"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
         /// </summary>
         /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
         /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
@@ -443,6 +453,7 @@ namespace System.Linq
         /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<float> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -479,6 +490,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<float> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<float>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -514,6 +526,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="double" /> values.
         /// </summary>
@@ -598,9 +611,10 @@ namespace System.Linq
                 }
             }
         }
+#endif
 
         /// <summary>
-        /// Computes the average of an async-enumerable sequence of <see cref="double"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
         /// </summary>
         /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
         /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
@@ -611,6 +625,7 @@ namespace System.Linq
         /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -647,6 +662,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<double>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -682,6 +698,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="decimal" /> values.
         /// </summary>
@@ -766,9 +783,10 @@ namespace System.Linq
                 }
             }
         }
+#endif
 
         /// <summary>
-        /// Computes the average of an async-enumerable sequence of <see cref="decimal"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
         /// </summary>
         /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
         /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
@@ -779,6 +797,7 @@ namespace System.Linq
         /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<decimal> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -815,6 +834,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<decimal> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<decimal>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -850,6 +870,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Int}" /> values.
         /// </summary>
@@ -950,18 +971,21 @@ namespace System.Linq
                 return null;
             }
         }
+#endif
 
         /// <summary>
-        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Int}"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
         /// </summary>
         /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
         /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
         /// <param name="selector">A transform function to invoke and await on each element of the source sequence.</param>
         /// <param name="cancellationToken">An optional cancellation token for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the average of the sequence of values, or <see langword="null"/> if the source sequence is empty.</returns>
+        /// <returns>A ValueTask containing the average of the sequence of values.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
+        /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double?> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1006,6 +1030,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double?> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<int?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1049,6 +1074,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Long}" /> values.
         /// </summary>
@@ -1149,18 +1175,21 @@ namespace System.Linq
                 return null;
             }
         }
+#endif
 
         /// <summary>
-        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Long}"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
         /// </summary>
         /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
         /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
         /// <param name="selector">A transform function to invoke and await on each element of the source sequence.</param>
         /// <param name="cancellationToken">An optional cancellation token for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the average of the sequence of values, or <see langword="null"/> if the source sequence is empty.</returns>
+        /// <returns>A ValueTask containing the average of the sequence of values.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
+        /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double?> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1205,6 +1234,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double?> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<long?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1248,6 +1278,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Float}" /> values.
         /// </summary>
@@ -1348,18 +1379,21 @@ namespace System.Linq
                 return null;
             }
         }
+#endif
 
         /// <summary>
-        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Float}"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
         /// </summary>
         /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
         /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
         /// <param name="selector">A transform function to invoke and await on each element of the source sequence.</param>
         /// <param name="cancellationToken">An optional cancellation token for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the average of the sequence of values, or <see langword="null"/> if the source sequence is empty.</returns>
+        /// <returns>A ValueTask containing the average of the sequence of values.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
+        /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<float?> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1404,6 +1438,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<float?> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<float?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1447,6 +1482,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Double}" /> values.
         /// </summary>
@@ -1547,18 +1583,21 @@ namespace System.Linq
                 return null;
             }
         }
+#endif
 
         /// <summary>
-        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Double}"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
         /// </summary>
         /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
         /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
         /// <param name="selector">A transform function to invoke and await on each element of the source sequence.</param>
         /// <param name="cancellationToken">An optional cancellation token for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the average of the sequence of values, or <see langword="null"/> if the source sequence is empty.</returns>
+        /// <returns>A ValueTask containing the average of the sequence of values.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
+        /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double?> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1603,6 +1642,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<double?> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<double?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1646,6 +1686,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Decimal}" /> values.
         /// </summary>
@@ -1746,18 +1787,21 @@ namespace System.Linq
                 return null;
             }
         }
+#endif
 
         /// <summary>
-        /// Computes the average of an async-enumerable sequence of <see cref="Nullable{Decimal}"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
         /// </summary>
         /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
         /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
         /// <param name="selector">A transform function to invoke and await on each element of the source sequence.</param>
         /// <param name="cancellationToken">An optional cancellation token for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the average of the sequence of values, or <see langword="null"/> if the source sequence is empty.</returns>
+        /// <returns>A ValueTask containing the average of the sequence of values.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
+        /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<decimal?> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1802,6 +1846,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
         private static ValueTask<decimal?> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<decimal?>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)

+ 19 - 2
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Average.Generated.tt

@@ -50,6 +50,7 @@ foreach (var o in os)
         typeStr = "Nullable{" + o.type.Substring(0, 1).ToUpper() + o.type.Substring(1, o.type.Length - 2) + "}";
     }
 #>
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the average of an async-enumerable sequence of <see cref="<#=typeStr#>" /> values.
         /// </summary>
@@ -214,8 +215,22 @@ else
 #>
             }
         }
+#endif
 
-        internal static ValueTask<<#=o.res#>> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
+        /// <summary>
+        /// Computes the average of an async-enumerable sequence of <see cref="int"/> values that are obtained by invoking an asynchronous transform function on each element of the source sequence and awaiting the result.
+        /// </summary>
+        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
+        /// <param name="source">An async-enumerable sequence of values to compute the average of.</param>
+        /// <param name="selector">A transform function to invoke and await on each element of the source sequence.</param>
+        /// <param name="cancellationToken">An optional cancellation token for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing the average of the sequence of values.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
+        /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
+        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
+        private static ValueTask<<#=o.res#>> AverageAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
                 throw Error.ArgumentNull(nameof(source));
@@ -290,7 +305,9 @@ else
         }
 
 #if !NO_DEEP_CANCELLATION
-        internal static ValueTask<<#=o.res#>> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
+        [GenerateAsyncOverload]
+        [Obsolete("Use Select then AverageAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its AverageAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use AverageAsync on the resulting sequence.")]
+        private static ValueTask<<#=o.res#>> AverageAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
                 throw Error.ArgumentNull(nameof(source));

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Cast.cs

@@ -13,6 +13,9 @@ namespace System.Linq
         // NB: This is a non-standard LINQ operator, because we don't have a non-generic IAsyncEnumerable.
         //     We're keeping it to enable `from T x in xs` binding in C#.
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.cast?view=net-9.0-pp
+
         /// <summary>
         /// Converts the elements of an async-enumerable sequence to the specified type.
         /// </summary>
@@ -40,5 +43,6 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Concat.cs

@@ -11,6 +11,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.concat?view=net-9.0-pp
+
         /// <summary>
         /// Concatenates the second async-enumerable sequence to the first async-enumerable sequence upon successful termination of the first.
         /// </summary>
@@ -253,5 +256,6 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 7 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Contains.cs

@@ -10,6 +10,12 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.containsasync?view=net-9.0-pp
+        //
+        // These two overloads are replaced by the single method above, which takes a comparer, but supplies a default
+        // value of null.
+
         /// <summary>
         /// Determines whether an async-enumerable sequence contains a specified element by using the default equality comparer.
         /// </summary>
@@ -78,5 +84,6 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 15 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Count.cs

@@ -11,6 +11,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.countasync?view=net-9.0-pp#system-linq-asyncenumerable-countasync-1(system-collections-generic-iasyncenumerable((-0))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns an async-enumerable sequence containing an <see cref="int" /> that represents the total number of elements in an async-enumerable sequence.
         /// </summary>
@@ -50,6 +53,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.countasync?view=net-9.0-pp#system-linq-asyncenumerable-countasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns an async-enumerable sequence containing an <see cref="int" /> that represents how many elements in the specified async-enumerable sequence satisfy a condition.
         /// </summary>
@@ -87,6 +92,14 @@ namespace System.Linq
                 return count;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.countasync?view=net-9.0-pp#system-linq-asyncenumerable-countasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-threading-cancellationtoken-system-threading-tasks-valuetask((system-boolean))))-system-threading-cancellationtoken)
+        // Two overloads here are replaced by a single method.
+        // System.Linq.AsyncEnumerable only supplies the async predicate form where the callback accepts a cancellation token, but
+        // the CountAwaitAsync version that does not take this does not add any additional functionality. Since developers will need
+        // to change their code in any case to move off these obsolete methods, it would not be particularly useful to add a
+        // non-cancellable async predicate overload in System.Interactive.Async.
 
         /// <summary>
         /// Counts the elements in an async-enumerable sequence that satisfy a condition.
@@ -98,6 +111,7 @@ namespace System.Linq
         /// <returns>A ValueTask containing the number of elements in the sequence that satisfy the predicate.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use CountAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the CountAwaitAsync functionality now exists as overloads of CountAsync.")]
         private static ValueTask<int> CountAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -127,6 +141,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use CountAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the CountAwaitWithCancellationAsync functionality now exists as overloads of CountAsync.")]
         [GenerateAsyncOverload]
         private static ValueTask<int> CountAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {

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

@@ -11,6 +11,7 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Returns the elements of the specified sequence or the type parameter's default value in a singleton sequence if the sequence is empty.
         /// </summary>
@@ -136,5 +137,6 @@ namespace System.Linq
                 return count == 0 ? 1 : count;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

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

@@ -10,6 +10,11 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.distinct?view=net-9.0-pp
+        // These two overloads are covered by a single method in System.Linq.AsyncEnumerable. Its only method
+        // takes a comparer, but specifies a default value of null.
+
         /// <summary>
         /// Returns an async-enumerable sequence that contains only distinct elements.
         /// </summary>
@@ -139,5 +144,6 @@ namespace System.Linq
                 return AsyncEnumerableHelpers.ToSet(_source, _comparer, cancellationToken);
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ElementAt.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.elementatasync?view=net-9.0-pp#system-linq-asyncenumerable-elementatasync-1(system-collections-generic-iasyncenumerable((-0))-system-int32-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the element at a specified index in a sequence.
         /// </summary>
@@ -66,5 +69,6 @@ namespace System.Linq
                 throw Error.ArgumentOutOfRange(nameof(index));
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ElementAtOrDefault.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.elementatordefaultasync?view=net-9.0-pp#system-linq-asyncenumerable-elementatordefaultasync-1(system-collections-generic-iasyncenumerable((-0))-system-int32-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the element at a specified index in a sequence or a default value if the index is out of range.
         /// </summary>
@@ -65,5 +68,6 @@ namespace System.Linq
                 return default;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Empty.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.empty?view=net-9.0-pp
+
         /// <summary>
         /// Returns an empty async-enumerable sequence.
         /// </summary>
@@ -50,5 +53,6 @@ namespace System.Linq
 
             public ValueTask DisposeAsync() => default;
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

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

@@ -10,6 +10,11 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.except?view=net-9.0-pp
+        //
+        // These two overloads are replaced by the single method above, which takes a comparer, but supplies a default
+        // value of null.
         /// <summary>
         /// Produces the set difference of two async-enumerable sequences by using the default equality comparer to compare values.
         /// </summary>
@@ -57,5 +62,6 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 11 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/First.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.firstasync?view=net-9.0-pp#system-linq-asyncenumerable-firstasync-1(system-collections-generic-iasyncenumerable((-0))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the first element of an async-enumerable sequence.
         /// </summary>
@@ -34,6 +37,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.firstasync?view=net-9.0-pp#system-linq-asyncenumerable-firstasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the first element of an async-enumerable sequence that satisfies the condition in the predicate.
         /// </summary>
@@ -60,6 +65,10 @@ namespace System.Linq
                 return first.HasValue ? first.Value : throw Error.NoElements();
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.firstasync?view=net-9.0-pp#system-linq-asyncenumerable-firstasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-threading-cancellationtoken-system-threading-tasks-valuetask((system-boolean))))-system-threading-cancellationtoken)
+        // That only offers the async-with-cancellation callback overload, but the simpler form offers no additional functionality.
 
         /// <summary>
         /// Returns the first element of an async-enumerable sequence that satisfies the condition in the predicate.
@@ -72,6 +81,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is <see langword="null"/>.</exception>
         /// <exception cref="InvalidOperationException">No element satisfies the condition in the predicate. -or- The source sequence is empty.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use FirstAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the FirstAwaitAsync functionality now exists as overloads of FirstAsync.")]
         private static ValueTask<TSource> FirstAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -91,6 +101,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use FirstAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the FirstAwaitWithCancellationAsync functionality now exists as overloads of FirstAsync.")]
         internal static ValueTask<TSource> FirstAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)

+ 10 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/FirstOrDefault.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.firstordefaultasync?view=net-9.0-pp#system-linq-asyncenumerable-firstordefaultasync-1(system-collections-generic-iasyncenumerable((-0))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the first element of an async-enumerable sequence, or a default value if no such element exists.
         /// </summary>
@@ -33,6 +36,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.firstordefaultasync?view=net-9.0-pp#system-linq-asyncenumerable-firstordefaultasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the first element of an async-enumerable sequence that satisfies the condition in the predicate, or a default value if no such element exists.
         /// </summary>
@@ -58,6 +63,9 @@ namespace System.Linq
                 return first.HasValue ? first.Value : default;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.firstordefaultasync?view=net-9.0-pp#system-linq-asyncenumerable-firstordefaultasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-threading-cancellationtoken-system-threading-tasks-valuetask((system-boolean))))-system-threading-cancellationtoken)
 
         /// <summary>
         /// Returns the first element of an async-enumerable sequence that satisfies the condition in the predicate, or a default value if no element satisfies the condition in the predicate.
@@ -69,6 +77,7 @@ namespace System.Linq
         /// <returns>A ValueTask containing the first element in the sequence that satisfies the predicate, or a default value if no element satisfies the predicate.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use FirstOrDefaultAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the FirstOrDefaultAwaitAsync functionality now exists as overloads of FirstOrDefaultAsync.")]
         private static ValueTask<TSource?> FirstOrDefaultAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -88,6 +97,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use FirstOrDefaultAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the FirstOrDefaultAwaitWithCancellationAsync functionality now exists as overloads of FirstOrDefaultAsync.")]
         private static ValueTask<TSource?> FirstOrDefaultAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)

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

@@ -27,6 +27,7 @@ namespace System.Linq
         /// <returns>Task that signals the termination of the sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="action"/> is null.</exception>
         /// <remarks>This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.</remarks>
+        [Obsolete("Use the language support for async foreach instead.")]
         public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -55,6 +56,7 @@ namespace System.Linq
         /// <returns>Task that signals the termination of the sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="action"/> is null.</exception>
         /// <remarks>This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.</remarks>
+        [Obsolete("Use the language support for async foreach instead.")]
         public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource, int> action, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -85,6 +87,7 @@ namespace System.Linq
         /// <returns>Task that signals the termination of the sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="action"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use the language support for async foreach instead.")]
         private static Task ForEachAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, Task> action, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -105,6 +108,7 @@ namespace System.Linq
 
         #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use the language support for async foreach instead.")]
         internal static Task ForEachAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, Task> action, CancellationToken cancellationToken)
         {
             if (source == null)
@@ -134,6 +138,7 @@ namespace System.Linq
         /// <returns>Task that signals the termination of the sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="action"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use the language support for async foreach instead.")]
         private static Task ForEachAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, Task> action, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -156,6 +161,7 @@ namespace System.Linq
 
         #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use the language support for async foreach instead.")]
         internal static Task ForEachAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, Task> action, CancellationToken cancellationToken)
         {
             if (source == null)

+ 47 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/GroupBy.cs

@@ -10,6 +10,17 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // The next two methods are replaced by a single method in System.Linq.AsyncEnumerable:
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.groupby?view=net-9.0-pp#system-linq-asyncenumerable-groupby-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1)))
+        // It has a different signature from both:
+        //  Returns an IAsyncEnumerable<IGrouping<TKey, TElement>>, which is not the same as IAsyncGrouping<TKey, TElement>
+        //  Supplies a default value of null for the comparer
+        // That second difference is why there's only the one overload.
+        // The first difference seems large: IAsyncGrouping returns each group as an IAsyncEnumerable. In practice,
+        // the grouping operators enumerate the source to completion before returning anything so in practice this
+        // async capability is not used, and just complicates things for the consumer.
+
         /// <summary>
         /// Groups the elements of an async-enumerable sequence according to a specified key selector function.
         /// </summary>
@@ -34,6 +45,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
         public static IAsyncEnumerable<IAsyncGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedAsyncEnumerable<TSource, TKey>(source, keySelector, comparer);
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Groups the elements of an async-enumerable sequence according to a specified key selector function.
@@ -45,6 +57,7 @@ namespace System.Linq
         /// <returns>A sequence of async-enumerable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwait functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<IAsyncGrouping<TKey, TSource>> GroupByAwaitCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector) =>
             new GroupedAsyncEnumerableWithTask<TSource, TKey>(source, keySelector, comparer: null);
 
@@ -59,18 +72,31 @@ namespace System.Linq
         /// <returns>A sequence of async-enumerable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwait functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<IAsyncGrouping<TKey, TSource>> GroupByAwaitCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedAsyncEnumerableWithTask<TSource, TKey>(source, keySelector, comparer);
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwaitWithCancellationAsync functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<IAsyncGrouping<TKey, TSource>> GroupByAwaitWithCancellationCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector) =>
             new GroupedAsyncEnumerableWithTaskAndCancellation<TSource, TKey>(source, keySelector, comparer: null);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwaitWithCancellationAsync functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<IAsyncGrouping<TKey, TSource>> GroupByAwaitWithCancellationCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedAsyncEnumerableWithTaskAndCancellation<TSource, TKey>(source, keySelector, comparer);
 #endif
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // The next two methods are replaced by a single method in System.Linq.AsyncEnumerable:
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.groupby?view=net-9.0-pp#system-linq-asyncenumerable-groupby-3(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1))-system-func((-0-2))-system-collections-generic-iequalitycomparer((-1)))
+        // It has a different signature from both:
+        //  Returns an IAsyncEnumerable<IGrouping<TKey, TElement>>, which is not the same as IAsyncGrouping<TKey, TElement>
+        //  Supplies a default value of null for the comparer
+        // That second difference is why there's only the one overload.
+        // The first difference seems large: IAsyncGrouping returns each group as an IAsyncEnumerable. In practice,
+        // the grouping operators enumerate the source to completion before returning anything so in practice this
+        // async capability is not used, and just complicates things for the consumer.
 
         /// <summary>
         /// Groups the elements of an async-enumerable sequence and selects the resulting elements by using a specified function.
@@ -100,6 +126,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> or <paramref name="comparer"/> is null.</exception>
         public static IAsyncEnumerable<IAsyncGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedAsyncEnumerable<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer);
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Groups the elements of an async-enumerable sequence and selects the resulting elements by using a specified function.
@@ -113,6 +140,7 @@ namespace System.Linq
         /// <returns>A sequence of async-enumerable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwait functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<IAsyncGrouping<TKey, TElement>> GroupByAwaitCore<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TSource, ValueTask<TElement>> elementSelector) =>
             new GroupedAsyncEnumerableWithTask<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer: null);
 
@@ -129,24 +157,30 @@ namespace System.Linq
         /// <returns>A sequence of async-enumerable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> or <paramref name="comparer"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwait functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<IAsyncGrouping<TKey, TElement>> GroupByAwaitCore<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TSource, ValueTask<TElement>> elementSelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedAsyncEnumerableWithTask<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer);
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwaitWithCancellationAsync functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<IAsyncGrouping<TKey, TElement>> GroupByAwaitWithCancellationCore<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TSource, CancellationToken, ValueTask<TElement>> elementSelector) =>
             new GroupedAsyncEnumerableWithTaskAndCancellation<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer: null);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwaitWithCancellationAsync functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<IAsyncGrouping<TKey, TElement>> GroupByAwaitWithCancellationCore<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TSource, CancellationToken, ValueTask<TElement>> elementSelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedAsyncEnumerableWithTaskAndCancellation<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer);
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.groupby?view=net-9.0-pp#system-linq-asyncenumerable-groupby-3(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1))-system-func((-1-system-collections-generic-ienumerable((-0))-2))-system-collections-generic-iequalitycomparer((-1)))
         public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IAsyncEnumerable<TSource>, TResult> resultSelector) =>
             new GroupedResultAsyncEnumerable<TSource, TKey, TResult>(source, keySelector, resultSelector, comparer: null);
 
         public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IAsyncEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedResultAsyncEnumerable<TSource, TKey, TResult>(source, keySelector, resultSelector, comparer);
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Groups the elements of an async-enumerable sequence according to a specified key selector function, and then applies a result selector function to each group.
@@ -160,6 +194,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence of results obtained by invoking and awaiting the result-selector function on each group.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="resultSelector"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwait functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<TResult> GroupByAwaitCore<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TKey, IAsyncEnumerable<TSource>, ValueTask<TResult>> resultSelector) =>
             new GroupedResultAsyncEnumerableWithTask<TSource, TKey, TResult>(source, keySelector, resultSelector, comparer: null);
 
@@ -176,24 +211,32 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence of results obtained by invoking and awaiting the result-selector function on each group.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="resultSelector"/> or <paramref name="comparer"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwait functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<TResult> GroupByAwaitCore<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TKey, IAsyncEnumerable<TSource>, ValueTask<TResult>> resultSelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedResultAsyncEnumerableWithTask<TSource, TKey, TResult>(source, keySelector, resultSelector, comparer);
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwaitWithCancellationAsync functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<TResult> GroupByAwaitWithCancellationCore<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TKey, IAsyncEnumerable<TSource>, CancellationToken, ValueTask<TResult>> resultSelector) =>
             new GroupedResultAsyncEnumerableWithTaskAndCancellation<TSource, TKey, TResult>(source, keySelector, resultSelector, comparer: null);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwaitWithCancellationAsync functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<TResult> GroupByAwaitWithCancellationCore<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TKey, IAsyncEnumerable<TSource>, CancellationToken, ValueTask<TResult>> resultSelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedResultAsyncEnumerableWithTaskAndCancellation<TSource, TKey, TResult>(source, keySelector, resultSelector, comparer);
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // This covers the next two
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.groupby?view=net-9.0-pp#system-linq-asyncenumerable-groupby-4(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-threading-cancellationtoken-system-threading-tasks-valuetask((-1))))-system-func((-0-system-threading-cancellationtoken-system-threading-tasks-valuetask((-2))))-system-func((-1-system-collections-generic-ienumerable((-2))-system-threading-cancellationtoken-system-threading-tasks-valuetask((-3))))-system-collections-generic-iequalitycomparer((-1)))
+
         public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, TResult> resultSelector) =>
             new GroupedResultAsyncEnumerable<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer: null);
 
         public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedResultAsyncEnumerable<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer);
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Groups the elements of an async-enumerable sequence according to a specified key-selector function, applies an element selector to each element of each group, then applies a result selector to each transformed group.
@@ -209,6 +252,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence of results obtained by invoking the result selector function on each group and awaiting the result.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> or <paramref name="resultSelector"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwait functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<TResult> GroupByAwaitCore<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TSource, ValueTask<TElement>> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, ValueTask<TResult>> resultSelector) =>
             new GroupedResultAsyncEnumerableWithTask<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer: null);
 
@@ -227,15 +271,18 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence of results obtained by invoking the result selector function on each group and awaiting the result.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> or <paramref name="resultSelector"/> or <paramref name="comparer"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwait functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<TResult> GroupByAwaitCore<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TSource, ValueTask<TElement>> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, ValueTask<TResult>> resultSelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedResultAsyncEnumerableWithTask<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer);
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwaitWithCancellationAsync functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<TResult> GroupByAwaitWithCancellationCore<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TSource, CancellationToken, ValueTask<TElement>> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, CancellationToken, ValueTask<TResult>> resultSelector) =>
             new GroupedResultAsyncEnumerableWithTaskAndCancellation<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer: null);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupByAwaitWithCancellationAsync functionality now exists as overloads of GroupBy.")]
         private static IAsyncEnumerable<TResult> GroupByAwaitWithCancellationCore<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TSource, CancellationToken, ValueTask<TElement>> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, CancellationToken, ValueTask<TResult>> resultSelector, IEqualityComparer<TKey>? comparer) =>
             new GroupedResultAsyncEnumerableWithTaskAndCancellation<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer);
 #endif

+ 9 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/GroupJoin.cs

@@ -10,6 +10,10 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.groupjoin?view=net-9.0-pp#system-linq-asyncenumerable-groupjoin-4(system-collections-generic-iasyncenumerable((-0))-system-collections-generic-iasyncenumerable((-1))-system-func((-0-2))-system-func((-1-2))-system-func((-0-system-collections-generic-ienumerable((-1))-3))-system-collections-generic-iequalitycomparer((-2)))
+        // The method above covers the next two overloads because it supplies a default null value for comparer.
+
         /// <summary>
         /// Correlates the elements of two async-enumerable sequences based on equality of keys and groups the results. The default equality comparer is used to compare keys.
         /// </summary>
@@ -75,12 +79,15 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupJoin. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupJoinAwait functionality now exists as overloads of GroupJoin.")]
         private static IAsyncEnumerable<TResult> GroupJoinAwaitCore<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, ValueTask<TKey>> outerKeySelector, Func<TInner, ValueTask<TKey>> innerKeySelector, Func<TOuter, IAsyncEnumerable<TInner>, ValueTask<TResult>> resultSelector) =>
             GroupJoinAwaitCore<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer: null);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupJoin. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupJoinAwait functionality now exists as overloads of GroupJoin.")]
         private static IAsyncEnumerable<TResult> GroupJoinAwaitCore<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, ValueTask<TKey>> outerKeySelector, Func<TInner, ValueTask<TKey>> innerKeySelector, Func<TOuter, IAsyncEnumerable<TInner>, ValueTask<TResult>> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             if (outer == null)
@@ -117,10 +124,12 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupJoin. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupJoinAwaitWithCancellation functionality now exists as overloads of GroupJoin.")]
         private static IAsyncEnumerable<TResult> GroupJoinAwaitWithCancellationCore<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, ValueTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, ValueTask<TKey>> innerKeySelector, Func<TOuter, IAsyncEnumerable<TInner>, CancellationToken, ValueTask<TResult>> resultSelector) =>
             GroupJoinAwaitWithCancellationCore<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer: null);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use GroupJoin. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the GroupJoinAwaitWithCancellation functionality now exists as overloads of GroupJoin.")]
         private static IAsyncEnumerable<TResult> GroupJoinAwaitWithCancellationCore<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, ValueTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, ValueTask<TKey>> innerKeySelector, Func<TOuter, IAsyncEnumerable<TInner>, CancellationToken, ValueTask<TResult>> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             if (outer == null)

+ 5 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Intersect.cs

@@ -10,6 +10,10 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.intersect?view=net-9.0-pp
+        // The method above covers the next two overloads because it supplies a default null value for comparer.
+
         /// <summary>
         /// Produces the set intersection of two async-enumerable sequences by using the default equality comparer to compare values.
         /// </summary>
@@ -57,5 +61,6 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 11 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Join.cs

@@ -10,6 +10,10 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.join?view=net-9.0-pp#system-linq-asyncenumerable-join-4(system-collections-generic-iasyncenumerable((-0))-system-collections-generic-iasyncenumerable((-1))-system-func((-0-2))-system-func((-1-2))-system-func((-0-1-3))-system-collections-generic-iequalitycomparer((-2)))
+        // The method above covers the next two overloads because it supplies a default null value for comparer.
+
         /// <summary>
         /// Correlates the elements of two sequences based on matching keys. The default equality comparer is used to compare keys.
         /// </summary>
@@ -91,12 +95,17 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.join?view=net-9.0-pp#system-linq-asyncenumerable-join-4(system-collections-generic-iasyncenumerable((-0))-system-collections-generic-iasyncenumerable((-1))-system-func((-0-system-threading-cancellationtoken-system-threading-tasks-valuetask((-2))))-system-func((-1-system-threading-cancellationtoken-system-threading-tasks-valuetask((-2))))-system-func((-0-1-system-threading-cancellationtoken-system-threading-tasks-valuetask((-3))))-system-collections-generic-iequalitycomparer((-2)))
 
         [GenerateAsyncOverload]
+        [Obsolete("Use Join. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the JoinAwait functionality now exists as overloads of Join.")]
         private static IAsyncEnumerable<TResult> JoinAwaitCore<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, ValueTask<TKey>> outerKeySelector, Func<TInner, ValueTask<TKey>> innerKeySelector, Func<TOuter, TInner, ValueTask<TResult>> resultSelector) =>
             JoinAwaitCore<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer: null);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use Join. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the JoinAwait functionality now exists as overloads of Join.")]
         private static IAsyncEnumerable<TResult> JoinAwaitCore<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, ValueTask<TKey>> outerKeySelector, Func<TInner, ValueTask<TKey>> innerKeySelector, Func<TOuter, TInner, ValueTask<TResult>> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             if (outer == null)
@@ -149,10 +158,12 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Join. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the JoinAwaitWithCancellation functionality now exists as overloads of Join.")]
         private static IAsyncEnumerable<TResult> JoinAwaitWithCancellationCore<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, ValueTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, ValueTask<TKey>> innerKeySelector, Func<TOuter, TInner, CancellationToken, ValueTask<TResult>> resultSelector) =>
             JoinAwaitWithCancellationCore<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer: null);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use Join. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the JoinAwaitWithCancellation functionality now exists as overloads of Join.")]
         private static IAsyncEnumerable<TResult> JoinAwaitWithCancellationCore<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, ValueTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, ValueTask<TKey>> innerKeySelector, Func<TOuter, TInner, CancellationToken, ValueTask<TResult>> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             if (outer == null)

+ 9 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Last.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.lastasync?view=net-9.0-pp#system-linq-asyncenumerable-lastasync-1(system-collections-generic-iasyncenumerable((-0))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the last element of an async-enumerable sequence.
         /// </summary>
@@ -34,6 +37,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.lastasync?view=net-9.0-pp#system-linq-asyncenumerable-lastasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the last element of an async-enumerable sequence that satisfies the condition in the predicate.
         /// </summary>
@@ -61,6 +66,8 @@ namespace System.Linq
             }
         }
 
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
         /// <summary>
         /// Returns the last element of an async-enumerable sequence that satisfies the condition in the predicate.
         /// </summary>
@@ -72,6 +79,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null.</exception>
         /// <exception cref="InvalidOperationException">(Asynchronous) No element satisfies the condition in the predicate. -or- The source sequence is empty.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use LastAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the LastAwaitAsync functionality now exists as overloads of LastAsync.")]
         private static ValueTask<TSource> LastAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -91,6 +99,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use LastAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the LastAwaitWithCancellationAsync functionality now exists as overloads of LastAsync.")]
         private static ValueTask<TSource> LastAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)

+ 10 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/LastOrDefault.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.lastordefaultasync?view=net-9.0-pp#system-linq-asyncenumerable-lastordefaultasync-1(system-collections-generic-iasyncenumerable((-0))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the last element of an async-enumerable sequence, or a default value if no such element exists.
         /// </summary>
@@ -33,6 +36,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.lastordefaultasync?view=net-9.0-pp#system-linq-asyncenumerable-lastordefaultasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the last element of an async-enumerable sequence that satisfies the condition in the predicate, or a default value if no such element exists.
         /// </summary>
@@ -58,6 +63,9 @@ namespace System.Linq
                 return last.HasValue ? last.Value : default;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.lastordefaultasync?view=net-9.0-pp#system-linq-asyncenumerable-lastordefaultasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-threading-cancellationtoken-system-threading-tasks-valuetask((system-boolean))))-system-threading-cancellationtoken)
 
         /// <summary>
         /// Returns the last element of an async-enumerable sequence that satisfies the condition in the predicate, or a default value if no such element exists.
@@ -69,6 +77,7 @@ namespace System.Linq
         /// <returns>ValueTask containing the last element in the async-enumerable sequence that satisfies the condition in the predicate, or a default value if no such element exists.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use LastOrDefaultAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the LastOrDefaultAwaitAsync functionality now exists as overloads of LastOrDefaultAsync.")]
         private static ValueTask<TSource?> LastOrDefaultAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -88,6 +97,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use LastOrDefaultAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the LastOrDefaultAwaitWithCancellationAsync functionality now exists as overloads of LastOrDefaultAsync.")]
         private static ValueTask<TSource?> LastOrDefaultAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)

+ 8 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/LongCount.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.longcountasync?view=net-9.0-pp#system-linq-asyncenumerable-longcountasync-1(system-collections-generic-iasyncenumerable((-0))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns an async-enumerable sequence containing an <see cref="long" /> that represents the total number of elements in an async-enumerable sequence.
         /// </summary>
@@ -43,6 +46,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.longcountasync?view=net-9.0-pp#system-linq-asyncenumerable-longcountasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns an async-enumerable sequence containing an <see cref="long" /> that represents how many elements in the specified async-enumerable sequence satisfy a condition.
         /// </summary>
@@ -80,6 +85,7 @@ namespace System.Linq
                 return count;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Returns an async-enumerable sequence containing a <see cref="long" /> that represents the number of elements in the specified async-enumerable sequence that satisfy a condition.
@@ -92,6 +98,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use LongCountAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the LongCountAwaitAsync functionality now exists as overloads of LongCountAsync.")]
         private static ValueTask<long> LongCountAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -122,6 +129,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use LongCountAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the LongCountAwaitWithCancellationAsync functionality now exists as overloads of LongCountAsync.")]
         private static ValueTask<long> LongCountAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)

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

@@ -10,6 +10,16 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.maxasync?view=net-9.0-pp
+        // The method above has a slightly different signature: it takes a comparer. In cases where the cancellationToken
+        // has not been supplied, or has been passed by name, that method is source-compatible with this one.
+        // However, anyone calling this method with an unnamed cancellationToken argument will get an error because
+        // the comparer argument comes before the cancellationToken argument. There's not much we can do about
+        // this because if we continue to offer this method, it will result in ambiguous matches. The least bad
+        // option seems to be to hide this method, and anyone who was relying on it taking a positional
+        // cancellation token argument will need to deal with the compilation error.
+
         /// <summary>
         /// Returns the maximum element in an async-enumerable sequence.
         /// </summary>
@@ -95,6 +105,8 @@ namespace System.Linq
             }
         }
 
+#endif
+
         /// <summary>
         /// Invokes a transform function on each element of a sequence and returns the maximum value.
         /// </summary>
@@ -106,6 +118,7 @@ namespace System.Linq
         /// <returns>A ValueTask containing a single element with the value that corresponds to the maximum element in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use MaxByAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality previously provided by the MaxAsync overload that took a selector callback now exists as an overload of MaxByAsync.")]
         public static ValueTask<TResult> MaxAsync<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -196,6 +209,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use MaxByAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality previously provided by MaxAwaitAsync now exists as an overload of MaxByAsync.")]
         private static ValueTask<TResult> MaxAwaitAsyncCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TResult>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -277,6 +291,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use MaxByAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality previously provided by MaxAwaitWithCancellationAsync now exists as an overload of MaxByAsync.")]
         private static ValueTask<TResult> MaxAwaitWithCancellationAsyncCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TResult>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)

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

@@ -10,6 +10,16 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.minasync?view=net-9.0-pp
+        // The method above has a slightly different signature: it takes a comparer. In cases where the cancellationToken
+        // has not been supplied, or has been passed by name, that method is source-compatible with this one.
+        // However, anyone calling this method with an unnamed cancellationToken argument will get an error because
+        // the comparer argument comes before the cancellationToken argument. There's not much we can do about
+        // this because if we continue to offer this method, it will result in ambiguous matches. The least bad
+        // option seems to be to hide this method, and anyone who was relying on it taking a positional
+        // cancellation token argument will need to deal with the compilation error.
+
         /// <summary>
         /// Returns the minimum element in an async-enumerable sequence.
         /// </summary>
@@ -96,6 +106,8 @@ namespace System.Linq
             }
         }
 
+#endif
+
         /// <summary>
         /// Invokes a transform function on each element of a sequence and returns the minimum value.
         /// </summary>
@@ -107,6 +119,7 @@ namespace System.Linq
         /// <returns>A ValueTask sequence containing a single element with the value that corresponds to the minimum element in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use MinByAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality previously provided by the MinAsync overload that took a selector callback now exists as an overload of MinByAsync.")]
         public static ValueTask<TResult> MinAsync<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -198,6 +211,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use MinByAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality previously provided by MinAwaitAsync now exists as an overload of MinByAsync.")]
         private static ValueTask<TResult> MinAwaitAsyncCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TResult>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -279,6 +293,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use MinByAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality previously provided by MinAwaitWithCancellationAsync now exists as an overload of MinByAsync.")]
         private static ValueTask<TResult> MinAwaitWithCancellationAsyncCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TResult>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)

Fișier diff suprimat deoarece este prea mare
+ 231 - 83
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/MinMax.Generated.cs


+ 38 - 1
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/MinMax.Generated.tt

@@ -33,6 +33,7 @@ foreach (var m in new[] { "Max", "Min" })
             typeStr = "Nullable{" + t.Substring(0, 1).ToUpper() + t.Substring(1, t.Length - 2) + "}";
         }
 #>
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Returns the <#=extremum#> value in an async-enumerable sequence of <see cref="<#=typeStr#>" /> values.
         /// </summary>
@@ -288,6 +289,7 @@ foreach (var m in new[] { "Max", "Min" })
 #>
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
 <#
 foreach (var overload in new[] {
@@ -299,7 +301,7 @@ foreach (var overload in new[] {
     var isAsync = overload.invoke.StartsWith("await");
     var isDeepCancellation = overload.selector.Contains("CancellationToken");
     var suffix = isAsync ? "Await" : "";
-    var visibility = isAsync ? "internal" : "public";
+    var visibility = isAsync ? "private" : "public";
     var core = isAsync ? "Core" : "";
 
     if (isDeepCancellation)
@@ -307,8 +309,34 @@ foreach (var overload in new[] {
         suffix += "WithCancellation";
 #>
 #if !NO_DEEP_CANCELLATION
+        [GenerateAsyncOverload]
+<#
+    } else if (isAsync)
+    {
+#>
+        /// <summary>
+        /// Invokes and awaits a transform function on each element of a sequence and returns the maximum <see cref="<#=typeStr#>"/> value.
+        /// </summary>
+        /// <typeparam name="TSource">Type of elements in the source sequence.</typeparam>
+        /// <param name="source">The source sequence.</param>
+        /// <param name="selector">An asynchronous transform function to invoke and await on each element of the source.</param>
+        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
+        /// <returns>A ValueTask containing the maximum value in the sequence.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
+        [GenerateAsyncOverload]
 <#
     }
+    if (isDeepCancellation || isAsync)
+    {
+#>
+        [Obsolete("Use <#=m#>ByAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the functionality previously provided by <#=m#><#=suffix#>Async now exists as an overload of <#=m#>ByAsync.")]
+<#
+    } else {
+#>
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+<#
+    }
+
 #>
         <#=visibility#> static ValueTask<<#=t#>> <#=m#><#=suffix#>Async<#=core#><TSource>(this IAsyncEnumerable<TSource> source, <#=overload.selector#> selector, CancellationToken cancellationToken = default)
         {
@@ -566,6 +594,15 @@ foreach (var overload in new[] {
     {
 #>
 #endif
+
+<#
+    }
+
+    if (!(isDeepCancellation || isAsync))
+    {
+#>
+#endif
+
 <#
     }
 }

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

@@ -17,6 +17,11 @@ namespace System.Linq
         //         the source is not an option, because it would require users to specify two type arguments, unlike
         //         what's done in Enumerable.OfType. Should we move this method to Ix, thus doing away with OfType
         //         in the API surface altogether?
+        // IDG 2025/09/30: System.Linq.AsyncEnumerable implemented this one despite the limitations (and despite
+        //         not implementing AsAsyncEnumerable).
+
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.oftype?view=net-9.0-pp
 
         /// <summary>
         /// Filters the elements of an async-enumerable sequence based on the specified type.
@@ -43,5 +48,6 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 55 - 1
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/OrderBy.cs

@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// 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. 
 
@@ -8,8 +8,13 @@ using System.Threading.Tasks;
 
 namespace System.Linq
 {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.orderby?view=net-9.0-pp#system-linq-asyncenumerable-orderby-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
+        // The method linked to above includes a comparer parameter with a default value of null.
+
         /// <summary>
         /// Sorts the elements of a sequence in ascending order according to a key.
         /// </summary>
@@ -21,6 +26,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         public static IOrderedAsyncEnumerable<TSource> OrderBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector) =>
             new OrderedAsyncEnumerable<TSource, TKey>(source, keySelector, comparer: null, descending: false, parent: null);
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Sorts the elements of a sequence in ascending order according to a key obtained by invoking a transform function on each element and awaiting the result.
@@ -32,15 +38,20 @@ namespace System.Linq
         /// <returns>An ordered async-enumerable sequence whose elements are sorted according to a key.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use OrderBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the OrderByAwait functionality now exists as overloads of OrderBy.")]
         private static IOrderedAsyncEnumerable<TSource> OrderByAwaitCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector) =>
             new OrderedAsyncEnumerableWithTask<TSource, TKey>(source, keySelector, comparer: null, descending: false, parent: null);
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use OrderBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the OrderByAwaitWithCancellation functionality now exists as overloads of OrderBy.")]
         private static IOrderedAsyncEnumerable<TSource> OrderByAwaitWithCancellationCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector) =>
             new OrderedAsyncEnumerableWithTaskAndCancellation<TSource, TKey>(source, keySelector, comparer: null, descending: false, parent: null);
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.orderby?view=net-9.0-pp#system-linq-asyncenumerable-orderby-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
+
         /// <summary>
         /// Sorts the elements of a sequence in ascending order by using a specified comparer.
         /// </summary>
@@ -53,6 +64,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         public static IOrderedAsyncEnumerable<TSource> OrderBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) =>
             new OrderedAsyncEnumerable<TSource, TKey>(source, keySelector, comparer, descending: false, parent: null);
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Sorts the elements of a sequence in ascending order by using a specified comparer. The keys are obtained by invoking the transform function on each element and awaiting the result.
@@ -65,15 +77,21 @@ namespace System.Linq
         /// <returns>An ordered async-enumerable sequence whose elements are sorted according to a key.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use OrderBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the OrderByAwait functionality now exists as overloads of OrderBy.")]
         private static IOrderedAsyncEnumerable<TSource> OrderByAwaitCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IComparer<TKey> comparer) =>
             new OrderedAsyncEnumerableWithTask<TSource, TKey>(source, keySelector, comparer, descending: false, parent: null);
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use OrderBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the OrderByAwaitWithCancellation functionality now exists as overloads of OrderBy.")]
         private static IOrderedAsyncEnumerable<TSource> OrderByAwaitWithCancellationCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer) =>
             new OrderedAsyncEnumerableWithTaskAndCancellation<TSource, TKey>(source, keySelector, comparer, descending: false, parent: null);
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.orderbydescending?view=net-9.0-pp#system-linq-asyncenumerable-orderbydescending-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
+        // The method linked to above includes a comparer parameter with a default value of null.
+
         /// <summary>
         /// Sorts the elements of a sequence in descending order according to a key.
         /// </summary>
@@ -85,6 +103,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         public static IOrderedAsyncEnumerable<TSource> OrderByDescending<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector) =>
             new OrderedAsyncEnumerable<TSource, TKey>(source, keySelector, comparer: null, descending: true, parent: null);
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Sorts the elements of a sequence in descending order according to a key obtained by invoking a transform function on each element and awaiting the result.
@@ -96,15 +115,20 @@ namespace System.Linq
         /// <returns>An ordered async-enumerable sequence whose elements are sorted in descending order according to a key.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use OrderByDescending. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the OrderByDescendingAwait functionality now exists as overloads of OrderByDescending.")]
         private static IOrderedAsyncEnumerable<TSource> OrderByDescendingAwaitCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector) =>
             new OrderedAsyncEnumerableWithTask<TSource, TKey>(source, keySelector, comparer: null, descending: true, parent: null);
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use OrderByDescending. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the OrderByDescendingAwaitWithCancellation functionality now exists as overloads of OrderByDescending.")]
         private static IOrderedAsyncEnumerable<TSource> OrderByDescendingAwaitWithCancellationCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector) =>
             new OrderedAsyncEnumerableWithTaskAndCancellation<TSource, TKey>(source, keySelector, comparer: null, descending: true, parent: null);
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.orderbydescending?view=net-9.0-pp#system-linq-asyncenumerable-orderbydescending-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
+
         /// <summary>
         /// Sorts the elements of a sequence in descending order by using a specified comparer.
         /// </summary>
@@ -117,6 +141,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         public static IOrderedAsyncEnumerable<TSource> OrderByDescending<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) =>
             new OrderedAsyncEnumerable<TSource, TKey>(source, keySelector, comparer, descending: true, parent: null);
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Sorts the elements of a sequence in descending order by using a specified comparer. The keys are obtained by invoking the transform function on each element and awaiting the result.
@@ -129,15 +154,21 @@ namespace System.Linq
         /// <returns>An ordered async-enumerable sequence whose elements are sorted in descending order according to a key.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use OrderByDescending. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the OrderByDescendingAwait functionality now exists as overloads of OrderByDescending.")]
         private static IOrderedAsyncEnumerable<TSource> OrderByDescendingAwaitCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IComparer<TKey> comparer) =>
             new OrderedAsyncEnumerableWithTask<TSource, TKey>(source, keySelector, comparer, descending: true, parent: null);
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use OrderByDescending. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the OrderByDescendingAwaitWithCancellation functionality now exists as overloads of OrderByDescending.")]
         private static IOrderedAsyncEnumerable<TSource> OrderByDescendingAwaitWithCancellationCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer) =>
             new OrderedAsyncEnumerableWithTaskAndCancellation<TSource, TKey>(source, keySelector, comparer, descending: true, parent: null);
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.thenby?view=net-9.0-pp#system-linq-asyncenumerable-thenby-2(system-linq-iorderedasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
+        // The method linked to above includes a comparer parameter with a default value of null.
+
         /// <summary>
         /// Performs a subsequent ordering of the elements in a sequence in ascending order according to a key.
         /// </summary>
@@ -154,6 +185,7 @@ namespace System.Linq
 
             return source.CreateOrderedEnumerable(keySelector, comparer: null, descending: false);
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Performs a subsequent ordering of the elements in a sequence in ascending order according to a key obtained by invoking a transform function on each element and awaiting the result.
@@ -165,6 +197,7 @@ namespace System.Linq
         /// <returns>An ordered async-enumerable whose elements are sorted according to a key.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use ThenBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ThenByAwait functionality now exists as overloads of ThenBy.")]
         private static IOrderedAsyncEnumerable<TSource> ThenByAwaitCore<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector)
         {
             if (source == null)
@@ -175,6 +208,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use ThenBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ThenByAwaitWithCancellation functionality now exists as overloads of ThenBy.")]
         private static IOrderedAsyncEnumerable<TSource> ThenByAwaitWithCancellationCore<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector)
         {
             if (source == null)
@@ -184,6 +218,9 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.thenby?view=net-9.0-pp#system-linq-asyncenumerable-thenby-2(system-linq-iorderedasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
+
         /// <summary>
         /// Performs a subsequent ordering of the elements in a sequence in ascending order by using a specified comparer.
         /// </summary>
@@ -201,6 +238,7 @@ namespace System.Linq
 
             return source.CreateOrderedEnumerable(keySelector, comparer, descending: false);
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Performs a subsequent ordering of the elements in a sequence in ascending order by using a specified comparer. The keys are obtained by invoking a transform function on each element and awaiting the result.
@@ -213,6 +251,7 @@ namespace System.Linq
         /// <returns>An ordered async-enumerable whose elements are sorted according to a key.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use ThenBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ThenByAwait functionality now exists as overloads of ThenBy.")]
         private static IOrderedAsyncEnumerable<TSource> ThenByAwaitCore<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IComparer<TKey> comparer)
         {
             if (source == null)
@@ -223,6 +262,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use ThenBy. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ThenByAwaitWithCancellation functionality now exists as overloads of ThenBy.")]
         private static IOrderedAsyncEnumerable<TSource> ThenByAwaitWithCancellationCore<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer)
         {
             if (source == null)
@@ -232,6 +272,10 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.thenbydescending?view=net-9.0-pp#system-linq-asyncenumerable-thenbydescending-2(system-linq-iorderedasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
+        // The method linked to above includes a comparer parameter with a default value of null.
+
         /// <summary>
         /// Performs a subsequent ordering of the elements in a sequence in descending order, according to a key.
         /// </summary>
@@ -248,6 +292,7 @@ namespace System.Linq
 
             return source.CreateOrderedEnumerable(keySelector, comparer: null, descending: true);
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Performs a subsequent ordering of the elements in a sequence in descending order, according to a key obtained by invoking a transform function on each element and awaiting the result.
@@ -259,6 +304,7 @@ namespace System.Linq
         /// <returns>An ordered async-enumerable sequence whose elements are sorted in descending order according to a key.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use ThenByDescending. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ThenByDescendingAwait functionality now exists as overloads of ThenByDescending.")]
         private static IOrderedAsyncEnumerable<TSource> ThenByDescendingAwaitCore<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector)
         {
             if (source == null)
@@ -269,6 +315,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use ThenByDescending. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ThenByDescendingAwaitWithCancellation functionality now exists as overloads of ThenByDescending.")]
         private static IOrderedAsyncEnumerable<TSource> ThenByDescendingAwaitWithCancellationCore<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector)
         {
             if (source == null)
@@ -278,6 +325,9 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.thenbydescending?view=net-9.0-pp#system-linq-asyncenumerable-thenbydescending-2(system-linq-iorderedasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-icomparer((-1)))
+
         /// <summary>
         /// Performs a subsequent ordering of the elements in a sequence in descending order by using a specified comparer.
         /// </summary>
@@ -295,6 +345,7 @@ namespace System.Linq
 
             return source.CreateOrderedEnumerable(keySelector, comparer, descending: true);
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Performs a subsequent ordering of the elements in a sequence in descending order by using a specified comparer. The keys are obtained by invoking a transform function on each element and awaiting the result.
@@ -307,6 +358,7 @@ namespace System.Linq
         /// <returns>An ordered async-enumerable sequence whose elements are sorted in descending order according to a key.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use ThenByDescending. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ThenByDescendingAwait functionality now exists as overloads of ThenByDescending.")]
         private static IOrderedAsyncEnumerable<TSource> ThenByDescendingAwaitCore<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IComparer<TKey> comparer)
         {
             if (source == null)
@@ -317,6 +369,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use ThenByDescending. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ThenByDescendingAwaitWithCancellation functionality now exists as overloads of ThenByDescending.")]
         private static IOrderedAsyncEnumerable<TSource> ThenByDescendingAwaitWithCancellationCore<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer)
         {
             if (source == null)
@@ -326,4 +379,5 @@ namespace System.Linq
         }
 #endif
     }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 }

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

@@ -9,6 +9,7 @@ using System.Threading.Tasks;
 
 namespace System.Linq
 {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     // NB: Large portions of the implementation are based on https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/OrderedEnumerable.cs.
 
     internal abstract class OrderedAsyncEnumerable<TElement> : AsyncIterator<TElement>, IOrderedAsyncEnumerable<TElement>, IAsyncPartition<TElement>
@@ -1216,4 +1217,5 @@ namespace System.Linq
         }
     }
 #endif
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 }

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Range.cs

@@ -11,6 +11,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.range?view=net-9.0-pp
+
         /// <summary>
         /// Generates an async-enumerable sequence of integral numbers within a specified range.
         /// </summary>
@@ -144,5 +147,6 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Repeat.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.repeat?view=net-9.0-pp
+
         /// <summary>
         /// Generates an async-enumerable sequence that repeats the given element the specified number of times.
         /// </summary>
@@ -99,5 +102,6 @@ namespace System.Linq
                 return false;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Reverse.cs

@@ -11,6 +11,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.reverse?view=net-9.0-pp
+
         /// <summary>
         /// Inverts the order of the elements in a sequence.
         /// </summary>
@@ -115,5 +118,6 @@ namespace System.Linq
                 return false;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 10 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Select.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.select?view=net-9.0-pp#system-linq-asyncenumerable-select-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1)))
+
         /// <summary>
         /// Projects each element of an async-enumerable sequence into a new form.
         /// </summary>
@@ -34,6 +37,8 @@ namespace System.Linq
             };
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.select?view=net-9.0-pp#system-linq-asyncenumerable-select-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-int32-1)))
+
         /// <summary>
         /// Projects each element of an async-enumerable sequence into a new form by incorporating the element's index.
         /// </summary>
@@ -67,6 +72,7 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Projects each element of an async-enumerable sequence into a new form by applying an asynchronous selector function to each member of the source sequence and awaiting the result.
@@ -78,6 +84,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence whose elements are the result of invoking the transform function on each element of the source sequence and awaiting the result.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectAwait functionality now exists as overloads of Select.")]
         private static IAsyncEnumerable<TResult> SelectAwaitCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TResult>> selector)
         {
             if (source == null)
@@ -95,6 +102,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectAwaitWithCancellation functionality now exists as overloads of Select.")]
         private static IAsyncEnumerable<TResult> SelectAwaitWithCancellationCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TResult>> selector)
         {
             if (source == null)
@@ -121,6 +129,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence whose elements are the result of invoking the transform function on each element and its index of the source sequence and awaiting the result.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use Select. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectAwait functionality now exists as overloads of Select.")]
         private static IAsyncEnumerable<TResult> SelectAwaitCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<TResult>> selector)
         {
             if (source == null)
@@ -148,6 +157,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use Select. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectAwaitWithCancellation functionality now exists as overloads of Select.")]
         private static IAsyncEnumerable<TResult> SelectAwaitWithCancellationCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, ValueTask<TResult>> selector)
         {
             if (source == null)

+ 24 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SelectMany.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.selectmany?view=net-9.0-pp#system-linq-asyncenumerable-selectmany-3(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-collections-generic-iasyncenumerable((-1))))-system-func((-0-1-2)))
+
         /// <summary>
         /// Projects each element of an async-enumerable sequence to an async-enumerable sequence and merges the resulting async-enumerable sequences into one async-enumerable sequence.
         /// </summary>
@@ -28,6 +31,7 @@ namespace System.Linq
 
             return new SelectManyAsyncIterator<TSource, TResult>(source, selector);
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         // REVIEW: Should we keep these overloads that return ValueTask<IAsyncEnumerable<TResult>>? One could argue the selector is async twice.
 
@@ -41,6 +45,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence whose elements are the result of invoking the one-to-many transform function on each element of the source sequence and awaiting the result.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use SelectMany. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectManyAwait functionality now exists as overloads of SelectMany.")]
         private static IAsyncEnumerable<TResult> SelectManyAwaitCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<IAsyncEnumerable<TResult>>> selector)
         {
             if (source == null)
@@ -53,6 +58,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use SelectMany. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectManyAwaitWithCancellation functionality now exists as overloads of SelectMany.")]
         private static IAsyncEnumerable<TResult> SelectManyAwaitWithCancellationCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<IAsyncEnumerable<TResult>>> selector)
         {
             if (source == null)
@@ -64,6 +70,9 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.selectmany?view=net-9.0-pp#system-linq-asyncenumerable-selectmany-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-int32-system-collections-generic-iasyncenumerable((-1)))))
+
         /// <summary>
         /// Projects each element of an async-enumerable sequence to an async-enumerable sequence by incorporating the element's index and merges the resulting async-enumerable sequences into one async-enumerable sequence.
         /// </summary>
@@ -102,6 +111,7 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Projects each element of an async-enumerable sequence into an async-enumerable sequence by incorporating the element's index and merges the resulting async-enumerable sequences into an async-enumerable sequence.
@@ -113,6 +123,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence who's elements are the result of invoking the one-to-many transform function on each element of the source sequence and awaiting the result.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use SelectMany. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectManyAwait functionality now exists as overloads of SelectMany.")]
         private static IAsyncEnumerable<TResult> SelectManyAwaitCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<IAsyncEnumerable<TResult>>> selector)
         {
             if (source == null)
@@ -145,6 +156,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use SelectMany. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectManyAwaitWithCancellation functionality now exists as overloads of SelectMany.")]
         private static IAsyncEnumerable<TResult> SelectManyAwaitWithCancellationCore<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, ValueTask<IAsyncEnumerable<TResult>>> selector)
         {
             if (source == null)
@@ -176,6 +188,9 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.selectmany?view=net-9.0-pp#system-linq-asyncenumerable-selectmany-3(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-collections-generic-iasyncenumerable((-1))))-system-func((-0-1-2)))
+
         /// <summary>
         /// Projects each element of an async-enumerable sequence to an async-enumerable sequence, invokes the result selector for the source element and each of the corresponding inner sequence's elements, and merges the results into one async-enumerable sequence.
         /// </summary>
@@ -211,6 +226,7 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Projects each element of an async-enumerable sequence to an async-enumerable sequence by awaiting the result of a transform function, invokes the result selector for each of the source elements and each of the corrasponding inner-sequence's elements and awaits the result, and merges the results into one async-enumerable sequence.
@@ -224,6 +240,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence whose elements are the result of invoking the one-to-many transform function <paramref name="collectionSelector"/> on each element of the input sequence, awaiting the result, applying <paramref name="resultSelector"/> to each element of the intermediate sequences along with their corrasponding source element and awaiting the result.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/>, <paramref name="collectionSelector"/>, or <paramref name="resultSelector"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use SelectMany. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectManyAwait functionality now exists as overloads of SelectMany.")]
         private static IAsyncEnumerable<TResult> SelectManyAwaitCore<TSource, TCollection, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<IAsyncEnumerable<TCollection>>> collectionSelector, Func<TSource, TCollection, ValueTask<TResult>> resultSelector)
         {
             if (source == null)
@@ -251,6 +268,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use SelectMany. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectManyAwaitWithCancellation functionality now exists as overloads of SelectMany.")]
         private static IAsyncEnumerable<TResult> SelectManyAwaitWithCancellationCore<TSource, TCollection, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<IAsyncEnumerable<TCollection>>> collectionSelector, Func<TSource, TCollection, CancellationToken, ValueTask<TResult>> resultSelector)
         {
             if (source == null)
@@ -277,6 +295,9 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.selectmany?view=net-9.0-pp#system-linq-asyncenumerable-selectmany-3(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-int32-system-collections-generic-ienumerable((-1))))-system-func((-0-1-2)))
+
         /// <summary>
         /// Projects each element of an async-enumerable sequence to an async-enumerable sequence by incorporating the element's index, invokes the result selector for the source element and each of the corresponding inner sequence's elements, and merges the results into one async-enumerable sequence.
         /// </summary>
@@ -319,6 +340,7 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Projects each element of an async-enumerable sequence to an async-enumerable sequence by awaiting the result of a transform function that incorporates each element's index,
@@ -333,6 +355,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence whose elements are the result of invoking the one-to-many transform function <paramref name="collectionSelector"/> on each element of the input sequence, awaiting the result, applying <paramref name="resultSelector"/> to each element of the intermediate sequences olong with their corrasponding source element and awaiting the result.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/>, <paramref name="collectionSelector"/>, or <paramref name="resultSelector"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use SelectMany. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectManyAwait functionality now exists as overloads of SelectMany.")]
         private static IAsyncEnumerable<TResult> SelectManyAwaitCore<TSource, TCollection, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<IAsyncEnumerable<TCollection>>> collectionSelector, Func<TSource, TCollection, ValueTask<TResult>> resultSelector)
         {
             if (source == null)
@@ -367,6 +390,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use SelectMany. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SelectManyAwaitWithCancellation functionality now exists as overloads of SelectMany.")]
         private static IAsyncEnumerable<TResult> SelectManyAwaitWithCancellationCore<TSource, TCollection, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, ValueTask<IAsyncEnumerable<TCollection>>> collectionSelector, Func<TSource, TCollection, CancellationToken, ValueTask<TResult>> resultSelector)
         {
             if (source == null)

+ 5 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SequenceEqual.cs

@@ -10,6 +10,10 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.sequenceequalasync?view=net-9.0-pp
+        // The method above covers the next two overloads because it supplies a default null value for comparer.
+
         /// <summary>
         /// Determines whether two sequences are equal by comparing the elements pairwise.
         /// </summary>
@@ -84,5 +88,6 @@ namespace System.Linq
                 return !await e2.MoveNextAsync();
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 8 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Single.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.singleasync?view=net-9.0-pp#system-linq-asyncenumerable-singleasync-1(system-collections-generic-iasyncenumerable((-0))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the only element of an async-enumerable sequence, and reports an exception if there is not exactly one element in the async-enumerable sequence.
         /// </summary>
@@ -56,6 +59,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.singleasync?view=net-9.0-pp#system-linq-asyncenumerable-singleasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the only element of an async-enumerable sequence that satisfies the condition in the predicate, and reports an exception if there is not exactly one element in the async-enumerable sequence.
         /// </summary>
@@ -101,6 +106,7 @@ namespace System.Linq
                 throw Error.NoElements();
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Returns the only element of an async-enumerable sequence that satisfies the condition in the asynchronous predicate, and reports an exception if there is not exactly one element in the async-enumerable sequence that matches the predicate.
@@ -113,6 +119,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null.</exception>
         /// <exception cref="InvalidOperationException">(Asynchronous) No element satisfies the condition in the predicate. -or- More than one element satisfies the condition in the predicate. -or- The source sequence is empty.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use SingleAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SingleAwaitAsync functionality now exists as overloads of SingleAsync.")]
         private static ValueTask<TSource> SingleAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -151,6 +158,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use SingleAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SingleAwaitWithCancellationAsync functionality now exists as overloads of SingleAsync.")]
         private static ValueTask<TSource> SingleAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)

+ 8 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SingleOrDefault.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.singleordefaultasync?view=net-9.0-pp#system-linq-asyncenumerable-singleordefaultasync-1(system-collections-generic-iasyncenumerable((-0))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the only element of an async-enumerable sequence, or a default value if the async-enumerable sequence is empty; this method reports an exception if there is more than one element in the async-enumerable sequence.
         /// </summary>
@@ -57,6 +60,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.singleordefaultasync?view=net-9.0-pp#system-linq-asyncenumerable-singleordefaultasync-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean))-system-threading-cancellationtoken)
+
         /// <summary>
         /// Returns the only element of an async-enumerable sequence that matches the predicate, or a default value if no such element exists; this method reports an exception if there is more than one element in the async-enumerable sequence.
         /// </summary>
@@ -102,6 +107,7 @@ namespace System.Linq
                 return default;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Returns the only element of an async-enumerable sequence that satisfies the condition in the asynchronous predicate, or a default value if no such element exists, and reports an exception if there is more than one element in the async-enumerable sequence that matches the predicate.
@@ -114,6 +120,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null.</exception>
         /// <exception cref="InvalidOperationException">(Asynchronous) More than one element satisfies the condition in the predicate.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use SingleOrDefaultAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SingleOrDefaultAwaitAsync functionality now exists as overloads of SingleOrDefaultAsync.")]
         private static ValueTask<TSource?> SingleOrDefaultAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -152,6 +159,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use SingleOrDefaultAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SingleOrDefaultAwaitWithCancellationAsync functionality now exists as overloads of SingleOrDefaultAsync.")]
         private static ValueTask<TSource?> SingleOrDefaultAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate, CancellationToken cancellationToken = default)
         {
             if (source == null)

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Skip.cs

@@ -8,6 +8,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.skip?view=net-9.0-pp
+
         /// <summary>
         /// Bypasses a specified number of elements in an async-enumerable sequence and then returns the remaining elements.
         /// </summary>
@@ -44,5 +47,6 @@ namespace System.Linq
 
             return new AsyncEnumerablePartition<TSource>(source, count, -1);
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SkipLast.cs

@@ -11,6 +11,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.skiplast?view=net-9.0-pp
+
         /// <summary>
         /// Bypasses a specified number of elements at the end of an async-enumerable sequence.
         /// </summary>
@@ -68,5 +71,6 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 10 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/SkipWhile.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.skipwhile?view=net-9.0-pp#system-linq-asyncenumerable-skipwhile-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean)))
+
         /// <summary>
         /// Bypasses elements in an async-enumerable sequence as long as a specified condition is true and then returns the remaining elements.
         /// </summary>
@@ -50,6 +53,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.skipwhile?view=net-9.0-pp#system-linq-asyncenumerable-skipwhile-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-int32-system-boolean)))
+
         /// <summary>
         /// Bypasses elements in an async-enumerable sequence as long as a specified condition is true and then returns the remaining elements.
         /// The element's index is used in the logic of the predicate function.
@@ -96,6 +101,7 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Bypasses elements in an async-enumerable sequence as long as a condition is true, and then returns the remaining elements.
@@ -106,6 +112,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing the elements in the source sequence starting at the first element that does not pass the test specified by the predicate.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use SkipWhile. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SkipWhileAwait functionality now exists as overloads of SkipWhile.")]
         private static IAsyncEnumerable<TSource> SkipWhileAwaitCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate)
         {
             if (source == null)
@@ -140,6 +147,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use SkipWhile. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SkipWhileAwaitWithCancellation functionality now exists as overloads of SkipWhile.")]
         private static IAsyncEnumerable<TSource> SkipWhileAwaitWithCancellationCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate)
         {
             if (source == null)
@@ -183,6 +191,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing the elements in the source sequence starting at the first element that does not pass the test specified by the predicate.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is <see langword="null"/>.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use SkipWhile. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SkipWhileAwait functionality now exists as overloads of SkipWhile.")]
         private static IAsyncEnumerable<TSource> SkipWhileAwaitCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<bool>> predicate)
         {
             if (source == null)
@@ -223,6 +232,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use SkipWhile. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the SkipWhileAwaitWithCancellation functionality now exists as overloads of SkipWhile.")]
         private static IAsyncEnumerable<TSource> SkipWhileAwaitWithCancellationCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, ValueTask<bool>> predicate)
         {
             if (source == null)

+ 50 - 100
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Sum.Generated.cs

@@ -10,6 +10,7 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="int" /> values.
         /// </summary>
@@ -40,6 +41,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="int" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -51,6 +53,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<int> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -78,16 +81,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="int"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<int> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int>> selector, CancellationToken cancellationToken = default)
         {
@@ -117,6 +111,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<int> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<int>> selector, CancellationToken cancellationToken = default)
         {
@@ -146,6 +141,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="long" /> values.
         /// </summary>
@@ -176,6 +172,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="long" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -187,6 +184,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<long> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -214,16 +212,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="long"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<long> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long>> selector, CancellationToken cancellationToken = default)
         {
@@ -253,6 +242,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<long> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<long>> selector, CancellationToken cancellationToken = default)
         {
@@ -282,6 +272,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="float" /> values.
         /// </summary>
@@ -309,6 +300,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="float" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -320,6 +312,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<float> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -344,16 +337,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="float"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<float> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float>> selector, CancellationToken cancellationToken = default)
         {
@@ -380,6 +364,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<float> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<float>> selector, CancellationToken cancellationToken = default)
         {
@@ -406,6 +391,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="double" /> values.
         /// </summary>
@@ -433,6 +419,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="double" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -444,6 +431,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<double> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -468,16 +456,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="double"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<double> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double>> selector, CancellationToken cancellationToken = default)
         {
@@ -504,6 +483,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<double> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<double>> selector, CancellationToken cancellationToken = default)
         {
@@ -530,6 +510,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="decimal" /> values.
         /// </summary>
@@ -557,6 +538,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="decimal" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -568,6 +550,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<decimal> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -592,16 +575,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="decimal"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<decimal> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal>> selector, CancellationToken cancellationToken = default)
         {
@@ -628,6 +602,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<decimal> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<decimal>> selector, CancellationToken cancellationToken = default)
         {
@@ -654,6 +629,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Int}" /> values.
         /// </summary>
@@ -684,6 +660,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Int}" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -695,6 +672,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<int?> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -722,16 +700,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="Nullable{Int}"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<int?> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int?>> selector, CancellationToken cancellationToken = default)
         {
@@ -761,6 +730,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<int?> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<int?>> selector, CancellationToken cancellationToken = default)
         {
@@ -790,6 +760,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Long}" /> values.
         /// </summary>
@@ -820,6 +791,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Long}" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -831,6 +803,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<long?> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -858,16 +831,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="Nullable{Long}"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<long?> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long?>> selector, CancellationToken cancellationToken = default)
         {
@@ -897,6 +861,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<long?> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<long?>> selector, CancellationToken cancellationToken = default)
         {
@@ -926,6 +891,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Float}" /> values.
         /// </summary>
@@ -953,6 +919,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Float}" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -964,6 +931,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<float?> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -988,16 +956,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="Nullable{Float}"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<float?> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float?>> selector, CancellationToken cancellationToken = default)
         {
@@ -1024,6 +983,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<float?> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<float?>> selector, CancellationToken cancellationToken = default)
         {
@@ -1050,6 +1010,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Double}" /> values.
         /// </summary>
@@ -1077,6 +1038,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Double}" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -1088,6 +1050,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<double?> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1112,16 +1075,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="Nullable{Double}"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<double?> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double?>> selector, CancellationToken cancellationToken = default)
         {
@@ -1148,6 +1102,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<double?> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<double?>> selector, CancellationToken cancellationToken = default)
         {
@@ -1174,6 +1129,7 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Decimal}" /> values.
         /// </summary>
@@ -1201,6 +1157,7 @@ namespace System.Linq
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="Nullable{Decimal}" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -1212,6 +1169,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<decimal?> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -1236,16 +1194,7 @@ namespace System.Linq
             }
         }
 
-        /// <summary>
-        /// Computes the sum of a sequence of <see cref="Nullable{Decimal}"/> values that are obtained by invoking a transform function on each element of the source sequence and awaiting the result.
-        /// </summary>
-        /// <typeparam name="TSource">The type of elements in the source sequence.</typeparam>
-        /// <param name="source">A sequence of values that are used to calculate a sum.</param>
-        /// <param name="selector">An asynchronous transform function to apply to each element.</param>
-        /// <param name="cancellationToken">The optional cancellation token to be used for cancelling the sequence at any time.</param>
-        /// <returns>A ValueTask containing the sum of the values in the source sequence.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is <see langword="null"/>.</exception>
-        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<decimal?> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal?>> selector, CancellationToken cancellationToken = default)
         {
@@ -1272,6 +1221,7 @@ namespace System.Linq
         }
 
 #if !NO_DEEP_CANCELLATION
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         [GenerateAsyncOverload]
         private static ValueTask<decimal?> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<decimal?>> selector, CancellationToken cancellationToken = default)
         {

+ 9 - 2
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Sum.Generated.tt

@@ -40,6 +40,7 @@ foreach (var o in os)
         typeStr = "Nullable{" + o.type.Substring(0, 1).ToUpper() + o.type.Substring(1, o.type.Length - 2) + "}";
     }
 #>
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
         /// <summary>
         /// Computes the sum of a sequence of <see cref="<#=typeStr#>" /> values.
         /// </summary>
@@ -83,6 +84,7 @@ else
                 return sum;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Computes the sum of a sequence of <see cref="<#=typeStr#>" /> values that are obtained by invoking a transform function on each element of the input sequence.
@@ -94,6 +96,7 @@ else
         /// <returns>An async-enumerable sequence containing a single element with the sum of the values in the source sequence.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
         public static ValueTask<<#=o.type#>> SumAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, <#=o.type#>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
@@ -134,7 +137,9 @@ else
             }
         }
 
-        internal static ValueTask<<#=o.type#>> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
+        [GenerateAsyncOverload]
+        private static ValueTask<<#=o.type#>> SumAwaitAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
                 throw Error.ArgumentNull(nameof(source));
@@ -175,7 +180,9 @@ else
         }
 
 #if !NO_DEEP_CANCELLATION
-        internal static ValueTask<<#=o.type#>> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
+        [Obsolete("Use Select then SumAsync. System.Linq.Async (a community-supported library) has been replaced by the (Microsoft supported) IAsyncEnumerable LINQ in System.Linq.AsyncEnumerable, and its SumAsync method does not include the overloads that take a selector. So you should use Select to perform the projection and then use SumAsync on the resulting sequence.")]
+        [GenerateAsyncOverload]
+        private static ValueTask<<#=o.type#>> SumAwaitWithCancellationAsyncCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
         {
             if (source == null)
                 throw Error.ArgumentNull(nameof(source));

+ 5 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Take.cs

@@ -8,6 +8,10 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.take?view=net-9.0-pp#system-linq-asyncenumerable-take-1(system-collections-generic-iasyncenumerable((-0))-system-int32)
+
         /// <summary>
         /// Returns a specified number of contiguous elements from the start of an async-enumerable sequence.
         /// </summary>
@@ -37,5 +41,6 @@ namespace System.Linq
 
             return new AsyncEnumerablePartition<TSource>(source, 0, count - 1);
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 5 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/TakeLast.cs

@@ -11,6 +11,10 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.takelast?view=net-9.0-pp
+
         /// <summary>
         /// Returns a specified number of contiguous elements from the end of an async-enumerable sequence.
         /// </summary>
@@ -77,5 +81,6 @@ namespace System.Linq
                 while (queue.Count > 0);
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 10 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/TakeWhile.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.takewhile?view=net-9.0-pp#system-linq-asyncenumerable-takewhile-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-boolean)))
+
         /// <summary>
         /// Returns elements from an async-enumerable sequence as long as a specified condition is true.
         /// </summary>
@@ -41,6 +44,8 @@ namespace System.Linq
             }
         }
 
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.takewhile?view=net-9.0-pp#system-linq-asyncenumerable-takewhile-1(system-collections-generic-iasyncenumerable((-0))-system-func((-0-system-int32-system-boolean)))
+
         /// <summary>
         /// Returns elements from an async-enumerable sequence as long as a specified condition is true.
         /// The element's index is used in the logic of the predicate function.
@@ -79,6 +84,7 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Returns elements from an async-enumerable sequence as long as a specified condition is true.
@@ -89,6 +95,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use TakeWhile. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the TakeWhileAwait functionality now exists as overloads of TakeWhile.")]
         private static IAsyncEnumerable<TSource> TakeWhileAwaitCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate)
         {
             if (source == null)
@@ -114,6 +121,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use TakeWhile. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the TakeWhileAwaitWithCancellation functionality now exists as overloads of TakeWhile.")]
         private static IAsyncEnumerable<TSource> TakeWhileAwaitWithCancellationCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate)
         {
             if (source == null)
@@ -148,6 +156,7 @@ namespace System.Linq
         /// <returns>An async-enumerable sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null.</exception>
         [GenerateAsyncOverload]
+        [Obsolete("Use TakeWhile. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the TakeWhileAwait functionality now exists as overloads of TakeWhile.")]
         private static IAsyncEnumerable<TSource> TakeWhileAwaitCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<bool>> predicate)
         {
             if (source == null)
@@ -180,6 +189,7 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use TakeWhile. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the TakeWhileAwaitWithCancellation functionality now exists as overloads of TakeWhile.")]
         private static IAsyncEnumerable<TSource> TakeWhileAwaitWithCancellationCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, ValueTask<bool>> predicate)
         {
             if (source == null)

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToArray.cs

@@ -10,6 +10,9 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.toarrayasync?view=net-9.0-pp
+
         /// <summary>
         /// Creates an array from an async-enumerable sequence.
         /// </summary>
@@ -29,5 +32,6 @@ namespace System.Linq
 
             return AsyncEnumerableHelpers.ToArray(source, cancellationToken);
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 8 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToAsyncEnumerable.Observable.cs

@@ -11,6 +11,13 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+
+        // Moved to AsyncEnumerableEx in System.Interactive.Async.
+        // System.Linq.AsyncEnumerable has chosen not to implement this. We continue to implement this because
+        // we believe it is a useful feature, but since it's now in the category of LINQ-adjacent functionality
+        // not built into the .NET runtime libraries, it now lives in System.Interactive.Async.
+
         /// <summary>
         /// Converts an observable sequence to an async-enumerable sequence.
         /// </summary>
@@ -218,5 +225,6 @@ namespace System.Linq
                 }
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

+ 7 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToAsyncEnumerable.Task.cs

@@ -9,6 +9,12 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // Moved to AsyncEnumerableEx in System.Interactive.Async.
+        // System.Linq.AsyncEnumerable has chosen not to implement this. We continue to implement this because
+        // we believe it is a useful feature, but since it's now in the category of LINQ-adjacent functionality
+        // not built into the .NET runtime libraries, it now lives in System.Interactive.Async.
+
         /// <summary>
         /// Converts a task to an async-enumerable sequence.
         /// </summary>
@@ -44,5 +50,6 @@ namespace System.Linq
                 return false;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     }
 }

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

@@ -9,6 +9,7 @@ using System.Threading.Tasks;
 
 namespace System.Linq
 {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
     public static partial class AsyncEnumerable
     {
         /// <summary>
@@ -301,4 +302,5 @@ namespace System.Linq
             bool ICollection<T>.IsReadOnly => _source.IsReadOnly;
         }
     }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 }

+ 20 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToDictionary.cs

@@ -10,6 +10,10 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.todictionaryasync?view=net-9.0-pp#system-linq-asyncenumerable-todictionaryasync-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1))-system-threading-cancellationtoken)
+        // That one overload covers the next two methods, because it supplieds a default comparer.
+
         /// <summary>
         /// Creates a dictionary from an async-enumerable sequence according to a specified key selector function.
         /// </summary>
@@ -59,6 +63,7 @@ namespace System.Linq
                 return d;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Creates a dictionary from an async-enumerable sequence by invoking a key-selector function on each element and awaiting the result.
@@ -72,6 +77,7 @@ namespace System.Linq
         /// <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>
         [GenerateAsyncOverload]
+        [Obsolete("Use ToDictionaryAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ToDictionaryAwaitAsync functionality now exists as overloads of ToDictionaryAsync.")]
         private static ValueTask<Dictionary<TKey, TSource>> ToDictionaryAwaitAsyncCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, CancellationToken cancellationToken = default) where TKey : notnull =>
             ToDictionaryAwaitAsyncCore<TSource, TKey>(source, keySelector, comparer: null, cancellationToken);
 
@@ -88,6 +94,7 @@ namespace System.Linq
         /// <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>
         [GenerateAsyncOverload]
+        [Obsolete("Use ToDictionaryAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ToDictionaryAwaitAsync functionality now exists as overloads of ToDictionaryAsync.")]
         private static ValueTask<Dictionary<TKey, TSource>> ToDictionaryAwaitAsyncCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, IEqualityComparer<TKey>? comparer, CancellationToken cancellationToken = default) where TKey : notnull
         {
             if (source == null)
@@ -114,10 +121,12 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use ToDictionaryAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ToDictionaryAwaitWithCancellationAsync functionality now exists as overloads of ToDictionaryAsync.")]
         private static ValueTask<Dictionary<TKey, TSource>> ToDictionaryAwaitWithCancellationAsyncCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, CancellationToken cancellationToken = default) where TKey : notnull =>
             ToDictionaryAwaitWithCancellationAsyncCore(source, keySelector, comparer: null, cancellationToken);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use ToDictionaryAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ToDictionaryAwaitWithCancellationAsync functionality now exists as overloads of ToDictionaryAsync.")]
         private static ValueTask<Dictionary<TKey, TSource>> ToDictionaryAwaitWithCancellationAsyncCore<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, IEqualityComparer<TKey>? comparer, CancellationToken cancellationToken = default) where TKey : notnull
         {
             if (source == null)
@@ -143,6 +152,12 @@ namespace System.Linq
         }
 #endif
 
+#if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
+        // https://learn.microsoft.com/en-us/dotnet/api/system.linq.asyncenumerable.todictionaryasync?view=net-9.0-pp#system-linq-asyncenumerable-todictionaryasync-2(system-collections-generic-iasyncenumerable((-0))-system-func((-0-1))-system-collections-generic-iequalitycomparer((-1))-system-threading-cancellationtoken)
+        // The method above provides the functionality for each of the next two methods, although because it does so with a
+        // single method that provides a default null value for the comparer, it it's not a strict source-compatible
+        // replacement. But there's not much we can do about that.
+
         /// <summary>
         /// Creates a dictionary from an async-enumerable sequence according to a specified key selector function, and an element selector function.
         /// </summary>
@@ -199,6 +214,7 @@ namespace System.Linq
                 return d;
             }
         }
+#endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
 
         /// <summary>
         /// Creates a dictionary from an async-enumerable sequence using the specified asynchronous key and element selector functions.
@@ -214,6 +230,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> is null.</exception>
         /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
         [GenerateAsyncOverload]
+        [Obsolete("Use ToDictionaryAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ToDictionaryAwaitAsync functionality now exists as overloads of ToDictionaryAsync.")]
         private static ValueTask<Dictionary<TKey, TElement>> ToDictionaryAwaitAsyncCore<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TSource, ValueTask<TElement>> elementSelector, CancellationToken cancellationToken = default) where TKey : notnull =>
             ToDictionaryAwaitAsyncCore<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer: null, cancellationToken);
 
@@ -232,6 +249,7 @@ namespace System.Linq
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="elementSelector"/> 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>
         [GenerateAsyncOverload]
+        [Obsolete("Use ToDictionaryAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ToDictionaryAwaitAsync functionality now exists as overloads of ToDictionaryAsync.")]
         private static ValueTask<Dictionary<TKey, TElement>> ToDictionaryAwaitAsyncCore<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TSource, ValueTask<TElement>> elementSelector, IEqualityComparer<TKey>? comparer, CancellationToken cancellationToken = default) where TKey : notnull
         {
             if (source == null)
@@ -261,10 +279,12 @@ namespace System.Linq
 
 #if !NO_DEEP_CANCELLATION
         [GenerateAsyncOverload]
+        [Obsolete("Use ToDictionaryAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ToDictionaryAwaitWithCancellationAsync functionality now exists as overloads of ToDictionaryAsync.")]
         private static ValueTask<Dictionary<TKey, TElement>> ToDictionaryAwaitWithCancellationAsyncCore<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TSource, CancellationToken, ValueTask<TElement>> elementSelector, CancellationToken cancellationToken = default) where TKey : notnull =>
             ToDictionaryAwaitWithCancellationAsyncCore(source, keySelector, elementSelector, comparer: null, cancellationToken);
 
         [GenerateAsyncOverload]
+        [Obsolete("Use ToDictionaryAsync. IAsyncEnumerable LINQ is now in System.Linq.AsyncEnumerable, and the ToDictionaryAwaitWithCancellationAsync functionality now exists as overloads of ToDictionaryAsync.")]
         private static ValueTask<Dictionary<TKey, TElement>> ToDictionaryAwaitWithCancellationAsyncCore<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TKey>> keySelector, Func<TSource, CancellationToken, ValueTask<TElement>> elementSelector, IEqualityComparer<TKey>? comparer, CancellationToken cancellationToken = default) where TKey : notnull
         {
             if (source == null)

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff