Просмотр исходного кода

Update Ix.NET for .NET 8.0 sdk (#2135)

* Make Ix homoiconicity generator nullable-aware
* Upgrade ApiCompare and Playground to .NET 8.0
* Fix diagnostics
* Removed old NO_ARRAY_EMPTY conditional sections as no build targets now set that
* Add .NET 8.0 targets for test projects
* Add readme explaining use of .NET Core 3.1 in tests
* Remove use of MSBuild.Sdk.Extras and step to build refs explicitly
* Replace erroneous net4.8 TFM with net48 in reference assemblies
Ian Griffiths 1 год назад
Родитель
Сommit
5f831de0bc
100 измененных файлов с 958 добавлено и 706 удалено
  1. 4 0
      .editorconfig
  2. 106 0
      Ix.NET/Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md
  3. 34 0
      Ix.NET/Source/.editorconfig
  4. 1 1
      Ix.NET/Source/ApiCompare/ApiCompare.csproj
  5. 91 113
      Ix.NET/Source/ApiCompare/Program.cs
  6. 61 18
      Ix.NET/Source/AsyncQueryableGenerator.t4
  7. 5 1
      Ix.NET/Source/Directory.Build.props
  8. 2 0
      Ix.NET/Source/FasterLinq/FasterLinq.csproj
  9. 5 6
      Ix.NET/Source/FasterLinq/Program.cs
  10. 22 6
      Ix.NET/Source/Ix.NET.sln
  11. 7 0
      Ix.NET/Source/NetCore31TestReadme.txt
  12. 3 9
      Ix.NET/Source/Playground/DemoAttribute.cs
  13. 1 1
      Ix.NET/Source/Playground/Playground.csproj
  14. 15 13
      Ix.NET/Source/Playground/Program.cs
  15. 2 1
      Ix.NET/Source/System.Interactive.Async.Providers.Tests/System.Interactive.Async.Providers.Tests.csproj
  16. 4 0
      Ix.NET/Source/System.Interactive.Async.Providers/System.Interactive.Async.Providers.csproj
  17. 71 71
      Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.cs
  18. 4 4
      Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.tt
  19. 9 2
      Ix.NET/Source/System.Interactive.Async.Tests/System.Interactive.Async.Tests.csproj
  20. 8 8
      Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/Buffer.cs
  21. 2 2
      Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/MaxBy.cs
  22. 2 2
      Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/MinBy.cs
  23. 4 0
      Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/Never.cs
  24. 0 15
      Ix.NET/Source/System.Interactive.Async/EmptyArray.cs
  25. 5 0
      Ix.NET/Source/System.Interactive.Async/System.Interactive.Async.csproj
  26. 1 1
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Generate.cs
  27. 16 15
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Merge.cs
  28. 3 3
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/MinBy.cs
  29. 4 6
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Never.cs
  30. 3 3
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Return.cs
  31. 6 0
      Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Timeout.cs
  32. 27 2
      Ix.NET/Source/System.Interactive.Providers/System.Interactive.Providers.csproj
  33. 2 2
      Ix.NET/Source/System.Interactive.Providers/System/Linq/QueryableEx.cs
  34. 8 2
      Ix.NET/Source/System.Interactive.Tests/System.Interactive.Tests.csproj
  35. 17 17
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Buffer.cs
  36. 3 3
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Case.cs
  37. 1 1
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Create.cs
  38. 4 4
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Distinct.cs
  39. 6 6
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/DistinctUntilChanged.cs
  40. 9 9
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Do.cs
  41. 3 3
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/DoWhile.cs
  42. 3 3
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Expand.cs
  43. 1 1
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Finally.cs
  44. 3 3
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/For.cs
  45. 2 2
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/ForEach.cs
  46. 1 1
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Generate.cs
  47. 5 5
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/If.cs
  48. 4 4
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/MaxBy.cs
  49. 9 9
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Memoize.cs
  50. 4 4
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/MinBy.cs
  51. 9 9
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/OnErrorResumeNext.cs
  52. 3 3
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Publish.cs
  53. 1 1
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Repeat.cs
  54. 1 1
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Retry.cs
  55. 4 4
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Scan.cs
  56. 3 3
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/SelectMany.cs
  57. 3 3
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Share.cs
  58. 1 1
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/SkipLast.cs
  59. 2 2
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/TakeLast.cs
  60. 1 1
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Using.cs
  61. 3 3
      Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/While.cs
  62. 0 2
      Ix.NET/Source/System.Interactive.Tests/Tests.cs
  63. 27 2
      Ix.NET/Source/System.Interactive/System.Interactive.csproj
  64. 1 1
      Ix.NET/Source/System.Interactive/System/Linq/MaxRefCountList.cs
  65. 1 1
      Ix.NET/Source/System.Interactive/System/Linq/Operators/Case.cs
  66. 2 6
      Ix.NET/Source/System.Interactive/System/Linq/Operators/Create.cs
  67. 1 1
      Ix.NET/Source/System.Interactive/System/Linq/Operators/If.cs
  68. 1 1
      Ix.NET/Source/System.Interactive/System/Linq/Operators/MaxByWithTies.cs
  69. 2 3
      Ix.NET/Source/System.Interactive/System/Linq/Operators/Memoize.cs
  70. 1 1
      Ix.NET/Source/System.Interactive/System/Linq/Operators/Publish.cs
  71. 2 7
      Ix.NET/Source/System.Interactive/System/Linq/Operators/Share.cs
  72. 1 1
      Ix.NET/Source/System.Interactive/System/Linq/Operators/SkipLast.cs
  73. 1 1
      Ix.NET/Source/System.Interactive/System/Linq/Operators/TakeLast.cs
  74. 2 2
      Ix.NET/Source/System.Interactive/System/Linq/Operators/Throw.cs
  75. 3 9
      Ix.NET/Source/System.Interactive/System/Linq/RefCountList.cs
  76. 2 1
      Ix.NET/Source/System.Linq.Async.Queryable.Tests/System.Linq.Async.Queryable.Tests.csproj
  77. 5 0
      Ix.NET/Source/System.Linq.Async.Queryable/System.Linq.Async.Queryable.csproj
  78. 1 1
      Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableQuery.cs
  79. 3 6
      Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableRewriter.cs
  80. 112 112
      Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncQueryable.Generated.cs
  81. 3 3
      Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncQueryable.Generated.tt
  82. 0 16
      Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncQueryable.cs
  83. 9 2
      Ix.NET/Source/System.Linq.Async.Tests/System.Linq.Async.Tests.csproj
  84. 9 9
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Aggregate.cs
  85. 1 1
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Any.cs
  86. 4 4
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Count.cs
  87. 2 2
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/First.cs
  88. 2 2
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/FirstOrDefault.cs
  89. 5 1
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/GroupBy.cs
  90. 4 0
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/GroupJoin.cs
  91. 19 19
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Join.cs
  92. 2 2
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Last.cs
  93. 2 2
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/LastOrDefault.cs
  94. 4 4
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/LongCount.cs
  95. 3 3
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Max.cs
  96. 3 3
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Min.cs
  97. 1 1
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Range.cs
  98. 2 2
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Reverse.cs
  99. 70 58
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Select.cs
  100. 1 1
      Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Single.cs

+ 4 - 0
.editorconfig

@@ -252,3 +252,7 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false
 csharp_space_between_method_declaration_parameter_list_parentheses = false
 csharp_space_between_parentheses = false
 csharp_space_between_square_brackets = false
+
+# Primary constructors
+# We find these something of a mixed bag.
+dotnet_diagnostic.IDE0290.severity = none

+ 106 - 0
Ix.NET/Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md

@@ -0,0 +1,106 @@
+# Apparent mismatches between lib and ref in the `System.Interactive` NuGet package
+
+The `System.Interactive` NuGet package contains the usual `lib` folder, and also `ref`, the standard folder for reference assemblies. But the set of target frameworks in these two folders is, rather unusually, different. This document explains why.
+
+## Status
+
+Fait acomplis.
+
+This dates back at least as far as 2018. The main purpose of this document (written in 2024) is to explain why it's like it is. The original thinking was lost in the mists of time, and it took considerable effort to work out why on earth it's like this. This ADR is intended to save others from the same extensive archaeology. And the discovery is important: if we hadn't managed to reverse engineer the apparent thinking behind this design choice, we might have dismissed it as a mistake. (Indeed, part of its current implementation _is_ a mistake.) But it turns out to serve an important purpose in a non-obvious way.
+
+
+## Authors
+
+@idg10 ([Ian Griffiths](https://endjin.com/who-we-are/our-people/ian-griffiths/)) wrote this document, but he would like to make it clear that he did not make the original design decision in question. He is merely documenting it.
+
+
+## Context
+
+At the time of writing this, the current version of `System.Interactive` is 6.0.1. If you inspect the NuGet package you will find that the lib and ref folders have different sets of frameworks:
+
+* `lib`
+    * `net6.0`
+    * `net48`
+    * `netstandard2.0`
+* `ref`
+    * `net4.8`
+    * `net6.0`
+    * `netstandard2.1`
+
+  
+The use of `net4.8` in `ref` seems to have been a bug: that should have been `net48`. (The main reason I am confident it's a bug, and not a clever but obscure trick that we've not understood, is that the [commit of 2021/12/06 that added this](https://github.com/dotnet/reactive/commit/a2410b2267abe193191f3894d243771ae4b126fd) used [`net48` in reference assemblies for one of the other packages](https://github.com/dotnet/reactive/commit/a2410b2267abe193191f3894d243771ae4b126fd#diff-3b568c93a468dab1b1a619a450bf1c4d88d3ec9539737d09fa6fb7659bc0ae5fR7), so this just seems to have been a slip.)
+
+The other discrepancy is that we have `netstandard2.0` in the `lib` folder but `netstandard2.1` in the ref folder. At first glance, this too looks quite a lot like a mistake, particularly when you examine the history. Here is the point in the release history at which the `ref` folder first started having a `netstandard2.1` folder:
+
+* v3.1.1:
+    * no reference assemblies
+    * folder supports .NET FX 4.5 and .NET Standard 1.0
+* v3.2.0
+    * reference assemblies for netcoreapp2.0, netstandard1.0, and netstandard2.1
+    * lib folder supports .NET FX 4.5 and .NET Standard 1.0, and .NET Standard 2.1
+
+When v3.2.0 shipped in July 2018, the latest .NET Core was  2.1, which had shipped in May 2018. .NET Standard 2.1 was not yet a thing, because that didn't appear until November 2018, when the oldest .NET to support it (.NET Core 3.0) shipped. So on a first inspection, Ix.NET declared reference assemblies for a target framework that simply didn't exist!
+
+And yet, on closer inspection, this appears to be deliberate. Looking at this commit:
+
+  https://github.com/dotnet/reactive/commit/0252fb537c9d335b9bc863b65291f152c07ba385
+
+  we see a [comment in Ix.NET/Source/refs/Directory.build.props](https://github.com/dotnet/reactive/commit/0252fb537c9d335b9bc863b65291f152c07ba385#diff-909504334cbab5c432709c95ae78c24fb2910d850958af2ef6de444b18e5c8ecR6) saying:
+  
+> This is here so we can create a fake .NET Standard 2.1 facade
+
+I can only guess that they knew .NET Standard 2.1 was coming, and wanted to ensure that `System.Interactive` was ready for it when it shipped.
+  
+So it was deliberate. But offering reference assemblies for a platform without any corresponding implementation for that platform is an odd choice. (And although at the time this was a placholder for a forthcoming .NET Standard version, it continued to look like this after .NET Standard 2.1 shipped. All subsequent Ix.NET releases have continued to provide `netstandard2.1` in the `ref` folder with no matching folder in `lib`. So it wasn't just a temporary measure.) What purpose does this serve?
+
+Some of the features that Ix offers eventually became available in .NET Core, such as `EnumerableEx.SkipLast`. This method exists in the implementation assemblies for every TFM of Ix.NET, but the `netstandard2.1` and `net6.0` reference assemblies omit it. This has the effect that if you're targetting any version of .NET recent enough to have these methods built into the .NET runtime libraries, the Ix.NET equivalents will:
+
+* appear not to exist at build time
+* still be available at runtime
+
+The non-availability at build time is important because these are extension methods. If multiple extension methods of the same name and for same type are available in the same namespace, you get compiler errors when you try to use them in the normal way. (E.g., .NET defines `System.Linq.Enumerable.SkipLast` and Ix.NET defines `System.Linq.EnumerableEx.SkipLast`, and both are defined as extension methods for `IEnumerable<T>`. If it weren't for this NuGet package trickery, any file that has `using System.Linq;` would bring both the Ix and .NET versions into scope, with no straightforward way to indicate which one you want. You can resolve this with some quite obscure use of `extern` aliases, but it's not at all obvious how. If anyone using `System.Interactive` had run into this the moment they upgraded to .NET Core 3.1, that would have been a bad experience.)
+
+By arranging for the `netstandard2.1` and `net6.0` reference assemblies to omit these methods, Ix.NET ensures that the C# compiler has no idea these methods even exist, avoiding the problem. But why do we need reference assemblies for this? Why not just omit the methods from the main assemblies? That's because you might depend on some library, `OldLib`, that was built for `netstandard2.0`, where, say, `SkipLast` is unavailable. `OldLib` might use Ix.NET's `EnumerableEx.SkipLast`, so that method really has to be there at runtime, even if you're running on, say, .NET 8.0. .NET 8.0 provides `Enumerable.SkipLast` but if `OldLib` is only available in `netstandard2.0` form it won't have access to that. It can only use the `Ix.NET` one. So that method has to be there at runtime.
+
+So the basic trick here is that Ix.NET provides one API surface area for backwards compatibility purposes and a slightly smaller API surface that it advertises to new code targeting the latest Ix.NET. The `lib` folder contains complete assemblies providing the former, and the `ref` folder contains reference assemblies providing the latter.
+
+This still doesn't make it obvious why it's useful for `ref` to include `netstandard2.1` when `lib` does not. If I've understood the original design here, the thinking is that on any runtime where `netstandard2.1` is available, methods like `Enumerable.SkipLast` are available in the runtime libraries, so libraries built for `netstandard2.1` should be using that built-in `Enumerable.SkipLast`, and not Ix.NET's `EnumerableEx.SkipLast`. At runtime, `netstandard2.1` libraries with a dependency on `System.Interactive` may well find themselves using the `lib\netstandard2.0` version (because there is no `lib\netstandard2.1` version). E.g.:
+
+| `MyLib` TFM | Ix Ref Assembly TFM (for `MyLib` build) | Runtime | Ix Lib Assembly TFM | `SkipLast` used by `MyLib`
+|--|--|--|--|--|
+| `netstandard2.0` | `netstandard2.0` | .NET Core 2.1 | `netstandard2.0` | Ix |
+| `netstandard2.0` | `netstandard2.0` | .NET 6.0 | `net6.0` | Ix |
+| `netstandard2.0` | `netstandard2.0` | .NET Framework | `net48` | Ix |
+| `netstandard2.1` | `netstandard2.1` | Mono | `netstandard2.0` | .NET Runtime Libraries |
+| `netstandard2.1` | `netstandard2.1` | Unity | `netstandard2.0` | .NET Runtime Libraries |
+| `netstandard2.1` | `netstandard2.1` | .NET Core 3.1 | `netstandard2.0` (Ix.NET 6.0.1 has no .NET Core 3.1 version so this is the only available option) | .NET Runtime Libraries |
+| `netstandard2.1` | `netstandard2.1` | .NET 6.0 | `net6.0` | .NET Runtime Libraries |
+| `netcore3.1` | `netstandard2.1` | .NET Core 3.1 | `netstandard2.0` | .NET Runtime Libraries |
+| `netcore3.1` | `netstandard2.1` | .NET 6.0 | `net6.0` | .NET Runtime Libraries |
+| `net48` | `net48`* | .NET 4.8 | `net48` | Ix |
+| `net6.0` | `net6.0` | .NET 6.0 | `net6.0` | .NET Runtime Libraries |
+
+\* although this table represents the design intent, the fact that the reference assemblies were accidentally given the non-existent TFM `net4.8` instead of `net48` means that things didn't work out as described in that row in practice. That mistake meant that for that row, it instead looked like this:
+
+| `MyLib` TFM | Ix Ref Assembly TFM (for `MyLib` build) | Runtime | Ix Lib Assembly TFM | `SkipLast` used by `MyLib`
+|--|--|--|--|--|
+| `net48` | `netstandard2.0` (oops) | .NET 4.8 | `net48` | Ix |
+
+The reason this went undetected is that it happened to produce the required outcome: the library uses Ix's `SkipLast`, which is what we need here because .NET 4.8 doesn't have that.
+
+The most interesting row of the first table is the second one: it's the one case where the Ix implementation is used even though the runtime (.NET 6.0) does offer `SkipLast`. It works out this way because the library is built against `netstandard2.0`, so that runtime-supplied `SkipLast` simply isn't part of the available surface area (and in the other two rows where the library was built against `netstandard2.0`, it's not just absent from the compile-time surface area on those rows, it's also absent at runtime, which is exactly why `netstandard2.0` library can't use it). This has to work: any library compiled in a world where the runtime doesn't offer `Enumerable.SkipLast`, and which chose to use Ix's `EnumerableEx.SkipLast`, must continue to work even if loaded into a newer runtime that does offer `Enumerable.SkipLast`. .NET does not provide any method-level equivalent of type forwarding, so there's no way to arrange for the library to get the runtime's `Enumerable.SkipLast` in these situations, so it just has to use the Ix.NET one. That's why when Ix.NET is loaded onto runtimes that offer `Enumerable.SkipLast`, it's necessary for it still to make `EnumerableEx.SkipLast` available in case there are libraries that need it. But it also needs to ensure that this API appears not to exist for any code compiling against a target where `Enumerable.SkipLast` will be available.
+
+
+## Decision
+
+We will continue to use the same technique, although with two changes:
+
+* we will fix the `net4.8`/`net48` bug
+* we will no longer use `MSBuild.Extras.SDK`
+
+This somewhat unusual mismatched `lib` vs `ref` folder setup was previously handled by `MSBuild.Extras.SDK`, but that package is no longer maintained. (It hasn't been updated since .NET 5.0 was the latest runtime.) When we moved to the 8.0 SDK, the reference assembly generation stopped working, so we've had to recreate the same result by supported means. (That is what necessitated the git archaeological dig that led to the writing of this document.)
+
+
+## Consequences
+
+By continuing the established practice, Ix.NET's `SkipLast` will continue to be available to library authors targeting `netstandard2.0`, and its presence will continue not to cause hard to resolve ambiguous method errors when using newer TFMs. By droping `MSBuild.Extras.SDK`, we'll be able to get things building again on .NET SDK 8.0. Future maintainers will likely continue to be confused by the mismatched `lib` and `ref` folders when they first come across it, but we're hopeful that the existence of this ADR will help.

+ 34 - 0
Ix.NET/Source/.editorconfig

@@ -0,0 +1,34 @@
+[*.cs]
+
+# Prevent IDE1006 (Naming rule violation) errors for non-public fields.
+#
+# Unfortunately, the codebase has not historically been entirely consistent with internal naming
+# conventions. Apparently this wasn't noticed by older analyzer tooling, but as of the .NET 7
+# era, the naming rules analyzers are a bit more particular, and cannot be configured in a way
+# that makes them happy with the code as it stands. We could rename all the relevant symbols,
+# but that doesn't seem like an especially good use of time, so for now, we're suppressing
+# diagnostics in certain cases.
+#
+# Static readonly fields
+#dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.severity = none
+
+# Internal fields
+dotnet_naming_symbols.internal_field_symbols.applicable_kinds           = field
+dotnet_naming_symbols.internal_field_symbols.applicable_accessibilities = internal
+
+dotnet_naming_rule.internal_instance_fields_must_be_camel_cased_underscore_prefix.symbols  = internal_field_symbols
+dotnet_naming_rule.internal_instance_fields_must_be_camel_cased_underscore_prefix.style    = camel_case_and_prefix_with_underscore_style
+#dotnet_naming_rule.internal_instance_fields_must_be_camel_cased_underscore_prefix.severity = none
+
+
+# Protected fields
+# Annoyingly, a protected field in an internal class cannot be distinguished from a protected field in a public
+# class. That's unfortunate, because the latter are publicly visible, but the former are not, so we don't really
+# want to enforce public naming conventions on them. We generally avoid publicly visible fields, so the majority
+# of protected fields are in fact in internal types, so we use naming conventions appropriate to those.
+dotnet_naming_symbols.protected_field_symbols.applicable_kinds           = field
+dotnet_naming_symbols.protected_field_symbols.applicable_accessibilities = protected
+
+dotnet_naming_rule.protected_instance_fields_must_be_camel_cased_underscore_prefix.symbols  = protected_field_symbols
+dotnet_naming_rule.protected_instance_fields_must_be_camel_cased_underscore_prefix.style    = camel_case_and_prefix_with_underscore_style
+dotnet_naming_rule.protected_instance_fields_must_be_camel_cased_underscore_prefix.severity = none

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

@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net8.0</TargetFramework>
   </PropertyGroup>
 
   <ItemGroup>

+ 91 - 113
Ix.NET/Source/ApiCompare/Program.cs

@@ -13,16 +13,16 @@ using System.Threading.Tasks;
 
 namespace ApiCompare
 {
-    class Program
+    internal class Program
     {
-        private static readonly Type asyncInterfaceType = typeof(IAsyncEnumerable<>);
-        private static readonly Type syncInterfaceType = typeof(IEnumerable<>);
+        private static readonly Type AsyncInterfaceType = typeof(IAsyncEnumerable<>);
+        private static readonly Type SyncInterfaceType = typeof(IEnumerable<>);
 
-        private static readonly Type asyncOrderedInterfaceType = typeof(IOrderedAsyncEnumerable<>);
-        private static readonly Type syncOrderedInterfaceType = typeof(IOrderedEnumerable<>);
+        private static readonly Type AsyncOrderedInterfaceType = typeof(IOrderedAsyncEnumerable<>);
+        private static readonly Type SyncOrderedInterfaceType = typeof(IOrderedEnumerable<>);
 
-        private static readonly string[] exceptions = new[]
-        {
+        private static readonly string[] Exceptions =
+        [
             "SkipLast",  // In .NET Core 2.0
             "TakeLast",  // In .NET Core 2.0
 
@@ -39,16 +39,16 @@ namespace ApiCompare
             "ToAsyncEnumerable",  // First-class conversions
             "ToEnumerable",       // First-class conversions
             "ToObservable",       // First-class conversions
-        };
+        ];
 
-        private static readonly TypeSubstitutor subst = new TypeSubstitutor(new Dictionary<Type, Type>
+        private static readonly TypeSubstitutor Subst = new(new Dictionary<Type, Type>
         {
-            { asyncInterfaceType, syncInterfaceType },
-            { asyncOrderedInterfaceType, syncOrderedInterfaceType },
+            { AsyncInterfaceType, SyncInterfaceType },
+            { AsyncOrderedInterfaceType, SyncOrderedInterfaceType },
             { typeof(IAsyncGrouping<,>), typeof(IGrouping<,>) },
         });
 
-        static void Main()
+        private static void Main()
         {
             var asyncOperatorsType = typeof(AsyncEnumerable);
             var syncOperatorsType = typeof(Enumerable);
@@ -56,22 +56,22 @@ namespace ApiCompare
             Compare(syncOperatorsType, asyncOperatorsType);
         }
 
-        static void Compare(Type syncOperatorsType, Type asyncOperatorsType)
+        private static void Compare(Type syncOperatorsType, Type asyncOperatorsType)
         {
-            var syncOperators = GetQueryOperators(new[] { syncInterfaceType, syncOrderedInterfaceType }, syncOperatorsType, exceptions);
-            var asyncOperators = GetQueryOperators(new[] { asyncInterfaceType, asyncOrderedInterfaceType }, asyncOperatorsType, exceptions);
+            var syncOperators = GetQueryOperators([SyncInterfaceType, SyncOrderedInterfaceType], syncOperatorsType, Exceptions);
+            var asyncOperators = GetQueryOperators([AsyncInterfaceType, AsyncOrderedInterfaceType], asyncOperatorsType, Exceptions);
 
             CompareFactories(syncOperators.Factories, asyncOperators.Factories);
             CompareQueryOperators(syncOperators.QueryOperators, asyncOperators.QueryOperators);
             CompareAggregates(syncOperators.Aggregates, asyncOperators.Aggregates);
         }
 
-        static void CompareFactories(ILookup<string, MethodInfo> syncFactories, ILookup<string, MethodInfo> asyncFactories)
+        private static void CompareFactories(ILookup<string, MethodInfo> syncFactories, ILookup<string, MethodInfo> asyncFactories)
         {
             CompareSets(syncFactories, asyncFactories, CompareFactoryOverloads);
         }
 
-        static void CompareFactoryOverloads(string name, IEnumerable<MethodInfo> syncMethods, IEnumerable<MethodInfo> asyncMethods)
+        private static void CompareFactoryOverloads(string name, IEnumerable<MethodInfo> syncMethods, IEnumerable<MethodInfo> asyncMethods)
         {
             var sync = GetSignatures(syncMethods).ToArray();
             var async = GetRewrittenSignatures(asyncMethods).ToArray();
@@ -105,12 +105,12 @@ namespace ApiCompare
             }
         }
 
-        static void CompareQueryOperators(ILookup<string, MethodInfo> syncOperators, ILookup<string, MethodInfo> asyncOperators)
+        private static void CompareQueryOperators(ILookup<string, MethodInfo> syncOperators, ILookup<string, MethodInfo> asyncOperators)
         {
             CompareSets(syncOperators, asyncOperators, CompareQueryOperatorsOverloads);
         }
 
-        static void CompareQueryOperatorsOverloads(string name, IEnumerable<MethodInfo> syncMethods, IEnumerable<MethodInfo> asyncMethods)
+        private static void CompareQueryOperatorsOverloads(string name, IEnumerable<MethodInfo> syncMethods, IEnumerable<MethodInfo> asyncMethods)
         {
             var sync = GetSignatures(syncMethods).ToArray();
             var async = GetRewrittenSignatures(asyncMethods).ToArray();
@@ -171,12 +171,12 @@ namespace ApiCompare
             }
         }
 
-        static void CompareAggregates(ILookup<string, MethodInfo> syncAggregates, ILookup<string, MethodInfo> asyncAggregates)
+        private static void CompareAggregates(ILookup<string, MethodInfo> syncAggregates, ILookup<string, MethodInfo> asyncAggregates)
         {
             CompareSets(syncAggregates, asyncAggregates, CompareAggregateOverloads);
         }
 
-        static void CompareAggregateOverloads(string name, IEnumerable<MethodInfo> syncMethods, IEnumerable<MethodInfo> asyncMethods)
+        private static void CompareAggregateOverloads(string name, IEnumerable<MethodInfo> syncMethods, IEnumerable<MethodInfo> asyncMethods)
         {
             var sync = GetSignatures(syncMethods).Select(GetAsyncAggregateSignature).ToArray();
             var async = GetRewrittenSignatures(asyncMethods).ToArray();
@@ -281,20 +281,16 @@ namespace ApiCompare
 
         private static Signature GetAsyncVariant(Signature signature)
         {
-            return new Signature
-            {
-                ParameterTypes = signature.ParameterTypes.Select(GetAsyncVariant).ToArray(),
-                ReturnType = signature.ReturnType
-            };
+            return new Signature(
+                parameterTypes: signature.ParameterTypes.Select(GetAsyncVariant).ToArray(),
+                returnType: signature.ReturnType);
         }
 
         private static Signature AppendCancellationToken(Signature signature)
         {
-            return new Signature
-            {
-                ParameterTypes = signature.ParameterTypes.Concat(new[] { typeof(CancellationToken) }).ToArray(),
-                ReturnType = signature.ReturnType
-            };
+            return new Signature(
+                parameterTypes: [.. signature.ParameterTypes, typeof(CancellationToken)],
+                returnType: signature.ReturnType);
         }
 
         private static Type GetAsyncVariant(Type type)
@@ -318,7 +314,7 @@ namespace ApiCompare
                     }
                     else
                     {
-                        return Expression.GetFuncType(args.Append(typeof(Task)).ToArray());
+                        return Expression.GetFuncType([.. args, typeof(Task)]);
                     }
                 }
             }
@@ -326,7 +322,7 @@ namespace ApiCompare
             return type;
         }
 
-        static void CompareSets(ILookup<string, MethodInfo> sync, ILookup<string, MethodInfo> async, Action<string, IEnumerable<MethodInfo>, IEnumerable<MethodInfo>> compareCore)
+        private static void CompareSets(ILookup<string, MethodInfo> sync, ILookup<string, MethodInfo> async, Action<string, IEnumerable<MethodInfo>, IEnumerable<MethodInfo>> compareCore)
         {
             var syncNames = sync.Select(g => g.Key).ToArray();
             var asyncNames = async.Select(g => g.Key).ToArray();
@@ -374,7 +370,7 @@ namespace ApiCompare
             }
         }
 
-        static Operators GetQueryOperators(Type[] interfaceTypes, Type operatorsType, string[] exclude)
+        private static Operators GetQueryOperators(Type[] interfaceTypes, Type operatorsType, string[] exclude)
         {
             //
             // Get all the static methods.
@@ -410,25 +406,23 @@ namespace ApiCompare
             // Return operators.
             //
 
-            return new Operators
-            {
-                Factories = factories.ToLookup(m => m.Name, m => m),
-                QueryOperators = queryOperators.ToLookup(m => m.Name, m => m),
-                Aggregates = aggregates.ToLookup(m => m.Name, m => m),
-            };
+            return new Operators(
+                Factories: factories.ToLookup(m => m.Name, m => m),
+                QueryOperators: queryOperators.ToLookup(m => m.Name, m => m),
+                Aggregates: aggregates.ToLookup(m => m.Name, m => m));
         }
 
-        static IEnumerable<Signature> GetSignatures(IEnumerable<MethodInfo> methods)
+        private static IEnumerable<Signature> GetSignatures(IEnumerable<MethodInfo> methods)
         {
             return methods.Select(m => GetSignature(m));
         }
 
-        static IEnumerable<Signature> GetRewrittenSignatures(IEnumerable<MethodInfo> methods)
+        private static IEnumerable<Signature> GetRewrittenSignatures(IEnumerable<MethodInfo> methods)
         {
             return GetSignatures(methods).Select(s => RewriteSignature(s));
         }
 
-        static Signature GetSignature(MethodInfo method)
+        private static Signature GetSignature(MethodInfo method)
         {
             if (method.IsGenericMethodDefinition)
             {
@@ -436,37 +430,31 @@ namespace ApiCompare
                 method = method.MakeGenericMethod(newArgs);
             }
 
-            return new Signature
-            {
-                Method = method,
-                ReturnType = method.ReturnType,
-                ParameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray()
-            };
+            return new Signature(
+                returnType: method.ReturnType,
+                parameterTypes: method.GetParameters().Select(p => p.ParameterType).ToArray(),
+                method: method);
         }
 
-        static Signature RewriteSignature(Signature signature)
+        private static Signature RewriteSignature(Signature signature)
         {
-            return new Signature
-            {
-                Method = signature.Method,
-                ReturnType = subst.Visit(signature.ReturnType),
-                ParameterTypes = subst.Visit(signature.ParameterTypes)
-            };
+            return new Signature(
+                returnType: Subst.Visit(signature.ReturnType),
+                parameterTypes: Subst.Visit(signature.ParameterTypes),
+                method: signature.Method);
         }
 
-        static Signature GetAsyncAggregateSignature(Signature signature)
+        private static Signature GetAsyncAggregateSignature(Signature signature)
         {
             var retType = signature.ReturnType == typeof(void) ? typeof(Task) : typeof(Task<>).MakeGenericType(signature.ReturnType);
 
-            return new Signature
-            {
-                Method = signature.Method,
-                ReturnType = retType,
-                ParameterTypes = signature.ParameterTypes
-            };
+            return new Signature(
+                returnType: retType,
+                parameterTypes: signature.ParameterTypes,
+                method: signature.Method);
         }
 
-        static string ToString(MethodInfo method)
+        private static string ToString(MethodInfo? method)
         {
             if (method == null)
             {
@@ -478,30 +466,31 @@ namespace ApiCompare
                 method = method.GetGenericMethodDefinition();
             }
 
-            return method.ToString();
+            return method.ToString() ?? "UNKNOWN";
         }
 
-        class Operators
-        {
-            public ILookup<string, MethodInfo> Factories;
-            public ILookup<string, MethodInfo> QueryOperators;
-            public ILookup<string, MethodInfo> Aggregates;
-        }
+        private record Operators(
+            ILookup<string, MethodInfo> Factories,
+            ILookup<string, MethodInfo> QueryOperators,
+            ILookup<string, MethodInfo> Aggregates);
 
-        class Signature : IEquatable<Signature>
+        private class Signature(
+            Type returnType,
+            Type[] parameterTypes,
+            MethodInfo? method = null) : IEquatable<Signature>
         {
-            public MethodInfo Method;
-            public Type ReturnType;
-            public Type[] ParameterTypes;
+            public MethodInfo? Method { get; } = method;
+            public Type ReturnType { get; } = returnType;
+            public Type[] ParameterTypes { get; } = parameterTypes;
 
             public static bool operator ==(Signature s1, Signature s2)
             {
-                if ((object)s1 == null && (object)s2 == null)
+                if (s1 is null && s2 is null)
                 {
                     return true;
                 }
 
-                if ((object)s1 == null || (object)s2 == null)
+                if (s1 is null || s2 is null)
                 {
                     return false;
                 }
@@ -514,24 +503,16 @@ namespace ApiCompare
                 return !(s1 == s2);
             }
 
-            public bool Equals(Signature s)
+            public bool Equals(Signature? s)
             {
-                return (object)s != null && ReturnType.Equals(s.ReturnType) && ParameterTypes.SequenceEqual(s.ParameterTypes);
+                return s is not null && ReturnType.Equals(s.ReturnType) && ParameterTypes.SequenceEqual(s.ParameterTypes);
             }
 
-            public override bool Equals(object obj)
-            {
-                if (obj is Signature s)
-                {
-                    return Equals(s);
-                }
-
-                return false;
-            }
+            public override bool Equals(object? obj) => obj is Signature s && Equals(s);
 
             public override int GetHashCode()
             {
-                return ParameterTypes.Concat(new[] { ReturnType }).Aggregate(0, (a, t) => a * 17 + t.GetHashCode());
+                return ParameterTypes.Concat([ReturnType]).Aggregate(0, (a, t) => a * 17 + t.GetHashCode());
             }
 
             public override string ToString()
@@ -540,13 +521,13 @@ namespace ApiCompare
             }
         }
 
-        class TypeVisitor
+        private class TypeVisitor
         {
             public virtual Type Visit(Type type)
             {
                 if (type.IsArray)
                 {
-                    if (type.GetElementType().MakeArrayType() == type)
+                    if (type.GetElementType()!.MakeArrayType() == type)
                     {
                         return VisitArray(type);
                     }
@@ -579,12 +560,12 @@ namespace ApiCompare
 
             protected virtual Type VisitArray(Type type)
             {
-                return Visit(type.GetElementType()).MakeArrayType();
+                return Visit(type.GetElementType() ?? throw new ArgumentException($"{type} does not have an element type")).MakeArrayType();
             }
 
             protected virtual Type VisitMultidimensionalArray(Type type)
             {
-                return Visit(type.GetElementType()).MakeArrayType(type.GetArrayRank());
+                return Visit(type.GetElementType() ?? throw new ArgumentException($"{type} does not have an element type")).MakeArrayType(type.GetArrayRank());
             }
 
             protected virtual Type VisitGenericTypeDefinition(Type type)
@@ -599,12 +580,12 @@ namespace ApiCompare
 
             protected virtual Type VisitByRef(Type type)
             {
-                return Visit(type.GetElementType()).MakeByRefType();
+                return Visit(type.GetElementType() ?? throw new ArgumentException($"{type} does not have an element type")).MakeByRefType();
             }
 
             protected virtual Type VisitPointer(Type type)
             {
-                return Visit(type.GetElementType()).MakePointerType();
+                return Visit(type.GetElementType() ?? throw new ArgumentException($"{type} does not have an element type")).MakePointerType();
             }
 
             protected virtual Type VisitSimple(Type type)
@@ -618,15 +599,8 @@ namespace ApiCompare
             }
         }
 
-        class TypeSubstitutor : TypeVisitor
+        private class TypeSubstitutor(Dictionary<Type, Type> map) : TypeVisitor
         {
-            private readonly Dictionary<Type, Type> map;
-
-            public TypeSubstitutor(Dictionary<Type, Type> map)
-            {
-                this.map = map;
-            }
-
             public override Type Visit(Type type)
             {
                 if (map.TryGetValue(type, out var subst))
@@ -638,33 +612,37 @@ namespace ApiCompare
             }
         }
 
-        private static readonly Type[] Wildcards = new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) };
+        private static readonly Type[] Wildcards = [typeof(T1), typeof(T2), typeof(T3), typeof(T4)];
+
+        private class T1 { }
+
+        private class T2 { }
+
+        private class T3 { }
 
-        class T1 { }
-        class T2 { }
-        class T3 { }
-        class T4 { }
+        private class T4 { }
     }
 
-    static class TypeExtensions
+    internal static class TypeExtensions
     {
         public static string ToCSharp(this Type type)
         {
             if (type.IsArray)
             {
-                if (type.GetElementType().MakeArrayType() == type)
+                var elementType = type.GetElementType()!;
+                if (elementType.MakeArrayType() == type)
                 {
-                    return type.GetElementType().ToCSharp() + "[]";
+                    return elementType.ToCSharp() + "[]";
                 }
                 else
                 {
-                    return type.GetElementType().ToCSharp() + "[" + new string(',', type.GetArrayRank() - 1) + "]";
+                    return elementType.ToCSharp() + "[" + new string(',', type.GetArrayRank() - 1) + "]";
                 }
             }
             else if (type.IsConstructedGenericType)
             {
                 var def = type.GetGenericTypeDefinition();
-                var defName = def.Name.Substring(0, def.Name.IndexOf('`'));
+                var defName = def.Name[..def.Name.IndexOf('`')];
 
                 return defName + "<" + string.Join(", ", type.GetGenericArguments().Select(ToCSharp)) + ">";
             }

+ 61 - 18
Ix.NET/Source/AsyncQueryableGenerator.t4

@@ -1,6 +1,7 @@
 <#@ assembly name="System.Core" #>
 <#@ assembly name="System.Runtime" #>
 <#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Reflection" #>
 <#@ import namespace="System.Text" #>
 <#@ import namespace="System.Threading" #>
 <#@ import namespace="System.Threading.Tasks" #>
@@ -8,29 +9,67 @@
 <#
 var infoFieldNames = new Dictionary<string, int>();
 
-var toQuotedImpl = default(Func<Type, int, bool, string>);
-toQuotedImpl = (t, i, b) =>
+var toQuotedImpl = default(Func<Type, ParameterInfo, int, bool, string>);
+toQuotedImpl = (t, paramObjectForAttributes, parameterIndex, notNestedGenericTypeParameter) =>
 {
 var name = t.Name;
 
+// We always want to look at the whole-type nullability, so we look at that now, and if it's a generic
+// type, we'll also go on to inspect per-type-parameter nullability.
+var nullableData = paramObjectForAttributes?.GetCustomAttributesData().SingleOrDefault(ad => ad.AttributeType.FullName == "System.Runtime.CompilerServices.NullableAttribute");
+bool wholeTypeNullable = false;
+if (nullableData is not null)
+{
+    if (nullableData.ConstructorArguments[0].Value is IReadOnlyList<CustomAttributeTypedArgument> nullableFlags)
+    {
+        // When we end up in this part, the type argument is, in practice, being used as the type argument to
+        // the actual type. E.g., ValueTask<TSource?>. So we need to look at the second nullable flag.
+        wholeTypeNullable = ((byte)nullableFlags[1].Value) == 2;
+    }
+    else if (nullableData.ConstructorArguments[0].Value is byte bv)
+    {
+        wholeTypeNullable = bv == 2;
+    }
+}
 if (t.IsGenericType)
 {
     var genDef = t.GetGenericTypeDefinition();
     name = genDef.Name.Substring(0, genDef.Name.LastIndexOf('`'));
 
-    var genArgs = "<" + string.Join(", ", t.GetGenericArguments().Select(a => toQuotedImpl(a, i, false))) + ">";
+    Type[] genericArguments = t.GetGenericArguments();
+    bool[] typeParamsNullable = new bool[genericArguments.Length];
+    if (nullableData is not null)
+    {
+        if (nullableData.ConstructorArguments[0].Value is IReadOnlyList<CustomAttributeTypedArgument> nullableFlags)
+        {
+            // There isn't a 1-1 correspondence between type parameters and nullable flags. Really we should be recursively
+            // walking the type parameters, but this hack suffices for the types we actually encounter in practice.
+            int flagIndex = 1;
+            for (int i = 0; i < typeParamsNullable.Length; ++i)
+            {
+                if (!genericArguments[i].IsValueType)
+                {
+                    if (flagIndex >= nullableFlags.Count) throw new InvalidOperationException($"Type {t} has {typeParamsNullable.Length} type params, but the associated nullable attribute on parameterinto {paramObjectForAttributes} has length {nullableFlags.Count}");
+                    typeParamsNullable[i] = ((byte)nullableFlags[flagIndex].Value) == 2;
+                    flagIndex += 1;
+                }
+            }
+        }
+    }
+
+    var genArgs = "<" + string.Join(", ", genericArguments.Select((a, i) => toQuotedImpl(a, null, parameterIndex, false) + (typeParamsNullable[i] ? "?" : ""))) + ">";
 
-    if (b)
+    if (notNestedGenericTypeParameter)
     {
         if (name == "Func" || name == "Action")
         {
             name = "Expression<" + name + genArgs + ">";
         }
-        else if (name == "IAsyncEnumerable" && i == 0)
+        else if (name == "IAsyncEnumerable" && parameterIndex == 0)
         {
             name = "IAsyncQueryable" + genArgs;
         }
-        else if (name == "IOrderedAsyncEnumerable" && i == 0)
+        else if (name == "IOrderedAsyncEnumerable" && parameterIndex == 0)
         {
             name = "IOrderedAsyncQueryable" + genArgs;
         }
@@ -38,6 +77,8 @@ if (t.IsGenericType)
         {
             name += genArgs;
         }
+
+        //if (wholeTypeNullable) { name += "?"; }
     }
     else
     {
@@ -48,12 +89,13 @@ if (t.IsGenericType)
         else
         {
             name += genArgs;
+            if (wholeTypeNullable) { name += "?"; }
         }
     }
 }
 else if (t.IsArray)
 {
-    var elem = toQuotedImpl(t.GetElementType(), i, b);
+    var elem = toQuotedImpl(t.GetElementType(), null, parameterIndex, notNestedGenericTypeParameter);
     name = elem + "[]";
 }
 else
@@ -86,12 +128,13 @@ else
     {
         name = "object";
     }
+    if (wholeTypeNullable) { name += "?"; }
 }
 
 return name;
 };
 
-var toQuoted = new Func<Type, int, string>((t, i) => toQuotedImpl(t, i, true));
+var toQuoted = new Func<Type, ParameterInfo, int, string>((t, paramObjectForAttributes, parameterIndex) => toQuotedImpl(t, paramObjectForAttributes, parameterIndex, true));
 #>
 #nullable enable
 
@@ -125,16 +168,16 @@ foreach (var m in asyncEnumerableType.GetMethods()
                         .OrderBy(m => m.Name)
                         .ThenBy(m => m.IsGenericMethod ? m.GetGenericArguments().Length : 0)
                         .ThenBy(m => m.GetParameters().Length)
-                        .ThenBy(m => string.Join(", ", m.GetParameters().Select((p, i) => toQuoted(p.ParameterType, i) + " " + p.Name))))
+                        .ThenBy(m => string.Join(", ", m.GetParameters().Select((p, i) => toQuoted(p.ParameterType, p, i) + " " + p.Name))))
 {
     var genArgs = m.GetGenericArguments();
 
-    var ret = toQuoted(m.ReturnType, 0);
+    var ret = toQuoted(m.ReturnType, m.ReturnParameter, 0);
     var name = m.Name;
 
     if (genArgs.Length > 0)
     {
-        name += "<" + string.Join(", ", genArgs.Select(a => a.Name)) + ">";
+        name += "<" + string.Join(", ", genArgs.Select((a, i) => a.Name)) + ">";
     }
 
     var isParams = false;
@@ -156,8 +199,8 @@ foreach (var m in asyncEnumerableType.GetMethods()
         }
     }
 
-    var pars = string.Join(", ", m.GetParameters().Select((p, i) => (i == parCount - 1 && isParams ? "params " : "") + toQuoted(p.ParameterType, i) + (nullableParameterNames.Contains(p.Name) ? "?" : "") + " " + p.Name + (i == parCount - 1 && lastParameterDefault ? " = default" : "")));
-    var quotedPars = string.Join(", ", m.GetParameters().Select((p, i) => "default(" + toQuoted(p.ParameterType, i) + ")"));
+    var pars = string.Join(", ", m.GetParameters().Select((p, i) => (i == parCount - 1 && isParams ? "params " : "") + toQuoted(p.ParameterType, p, i) + (nullableParameterNames.Contains(p.Name) ? "?" : "") + " " + p.Name + (i == parCount - 1 && lastParameterDefault ? " = default" : "")));
+    var quotedPars = string.Join(", ", m.GetParameters().Select((p, i) => "default(" + toQuoted(p.ParameterType, p, i) + ")"));
 
     if (m.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), true))
     {
@@ -193,7 +236,7 @@ foreach (var m in asyncEnumerableType.GetMethods()
 
     infoName += infoNameId;
 
-    var infoSignature = string.Join(", ", m.GetParameters().Select((p, i) => toQuoted(p.ParameterType, i)).Concat(new[] { toQuoted(m.ReturnType, 0) }));
+    var infoSignature = string.Join(", ", m.GetParameters().Select((p, i) => toQuoted(p.ParameterType, p, i)).Concat(new[] { toQuoted(m.ReturnType, m.ReturnParameter, 0) }));
 
     foreach (var genArg in genArgs)
     {
@@ -219,7 +262,7 @@ foreach (var m in asyncEnumerableType.GetMethods()
 
         if (td.Name.EndsWith("Task`1")) // NB: Covers Task and ValueTask
         {
-            factory = "ExecuteAsync<" + toQuotedImpl(m.ReturnType.GetGenericArguments()[0], -1, false) + ">";
+            factory = "ExecuteAsync<" + toQuotedImpl(m.ReturnType.GetGenericArguments()[0], m.ReturnParameter, -1, false) + ">";
 
             var last = m.GetParameters().Last();
             if (last.ParameterType == typeof(CancellationToken))
@@ -233,11 +276,11 @@ foreach (var m in asyncEnumerableType.GetMethods()
         }
         else if (td == typeof(IAsyncEnumerable<>) || td == typeof(IOrderedAsyncEnumerable<>))
         {
-            factory = "CreateQuery<" + toQuotedImpl(m.ReturnType.GetGenericArguments()[0], -1, false) + ">";
+            factory = "CreateQuery<" + toQuotedImpl(m.ReturnType.GetGenericArguments()[0], null, -1, false) + ">";
 
             if (td == typeof(IOrderedAsyncEnumerable<>))
             {
-                cast = "(" + toQuoted(m.ReturnType, 0) + ")";
+                cast = "(" + toQuoted(m.ReturnType, null, 0) + ")";
             }
         }
     }
@@ -274,7 +317,7 @@ foreach (var m in asyncEnumerableType.GetMethods()
         
         if (!add)
         {
-            quotedArgs.Add("Expression.Constant(" + p.Name + ", typeof(" + toQuoted(pt, -1) + "))");
+            quotedArgs.Add("Expression.Constant(" + p.Name + ", typeof(" + toQuoted(pt, null, -1) + "))");
         }
 
         n++;

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

@@ -10,7 +10,11 @@
     <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
     <SignAssembly>true</SignAssembly>
     <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)ReactiveX.snk</AssemblyOriginatorKeyFile>
-    <NoWarn>$(NoWarn);1701;1702;CS1591;NU5105</NoWarn>
+    <!--
+    IDE0056 Suggests using range-based indexing, which doesn't work on .NET 4.8 (even in cases where it would compile down to code with no dependency on Index or Range).
+    IDE0270 Null check can be simplified. Tends to suggest using for exception throwing cases even when the resulting code would be overly complex.
+    -->
+    <NoWarn>$(NoWarn);1701;1702;CS1591;NU5105;IDE0056;IDE0270</NoWarn>
     <DefaultLanguage>en-US</DefaultLanguage>
     <IsTestProject>$(MSBuildProjectName.Contains('Test'))</IsTestProject>
     <EmbedUntrackedSources>true</EmbedUntrackedSources>

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

@@ -3,6 +3,8 @@
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net6.0</TargetFramework>
+
+    <NoWarn>$(NoWarn);IDE0007;IDE0034;IDE0040;IDE0063;IDE0090;IDE1006</NoWarn>
   </PropertyGroup>
 
 </Project>

+ 5 - 6
Ix.NET/Source/FasterLinq/Program.cs

@@ -4,6 +4,8 @@
 
 #nullable disable
 
+#pragma warning disable CS0436 // Interface definitions conflict with .NET Runtime. This brings its own older definitions of various async interfaces.
+
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -15,7 +17,7 @@ namespace FasterLinq
 {
     class Program
     {
-        static void Main(string[] args)
+        static void Main()
         {
             var N = 4;
 
@@ -808,12 +810,9 @@ namespace System.Labs.Linq
 
             try
             {
-                while (true)
+                while (await e.MoveNextAsync().ConfigureAwait(false))
                 {
-                    while (await e.MoveNextAsync().ConfigureAwait(false))
-                    {
-                        res = await aggregate(res, e.Current).ConfigureAwait(false);
-                    }
+                    res = await aggregate(res, e.Current).ConfigureAwait(false);
                 }
             }
             finally

+ 22 - 6
Ix.NET/Source/Ix.NET.sln

@@ -4,6 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
 VisualStudioVersion = 17.2.32131.331
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{87534290-A7A6-47A4-9A3A-D0D21A9AD1D4}"
+	ProjectSection(SolutionItems) = preProject
+		NetCore31TestReadme.txt = NetCore31TestReadme.txt
+	EndProjectSection
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B733D97A-F1ED-4FC3-BF8E-9AC47A89DE96}"
 	ProjectSection(SolutionItems) = preProject
@@ -12,15 +15,20 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
 		CodeCoverage.runsettings = CodeCoverage.runsettings
 		Directory.build.props = Directory.build.props
 		Directory.build.targets = Directory.build.targets
-		global.json = global.json
 		version.json = version.json
 	EndProjectSection
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive", "System.Interactive\System.Interactive.csproj", "{FF97CD0F-8108-4B66-8A34-42190B459180}"
+	ProjectSection(ProjectDependencies) = postProject
+		{2EC0C302-B029-4DDB-AC91-000BF11006AD} = {2EC0C302-B029-4DDB-AC91-000BF11006AD}
+	EndProjectSection
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive.Async", "System.Interactive.Async\System.Interactive.Async.csproj", "{A9F6D09B-15B9-4CE8-867F-6F3383C5F247}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive.Providers", "System.Interactive.Providers\System.Interactive.Providers.csproj", "{CA7B7136-13EE-4F01-BC22-722875EE8569}"
+	ProjectSection(ProjectDependencies) = postProject
+		{5DF341BE-B369-4250-AFD4-604DE8C95E45} = {5DF341BE-B369-4250-AFD4-604DE8C95E45}
+	EndProjectSection
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive.Async.Providers", "System.Interactive.Async.Providers\System.Interactive.Async.Providers.csproj", "{33691BB5-DD5B-4FED-8EE3-52CEE0DE2550}"
 EndProject
@@ -29,6 +37,9 @@ EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive.Async.Tests", "System.Interactive.Async.Tests\System.Interactive.Async.Tests.csproj", "{172BD8C4-5C3E-4928-9D3F-746CF336FFEC}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Linq.Async", "System.Linq.Async\System.Linq.Async.csproj", "{9B1E5420-E8F3-4B5F-A11A-4D18578F50CE}"
+	ProjectSection(ProjectDependencies) = postProject
+		{1754B36C-D0DB-4E5D-8C30-1F116046DC0F} = {1754B36C-D0DB-4E5D-8C30-1F116046DC0F}
+	EndProjectSection
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Linq.Async.Queryable", "System.Linq.Async.Queryable\System.Linq.Async.Queryable.csproj", "{513F9ABD-4FB8-4AC1-89DA-C3300399F34C}"
 EndProject
@@ -53,16 +64,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Refs", "Refs", "{A3D72E6E-4
 		refs\Directory.build.props = refs\Directory.build.props
 	EndProjectSection
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive", "refs\System.Interactive.Ref\System.Interactive.csproj", "{2EC0C302-B029-4DDB-AC91-000BF11006AD}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive", "refs\System.Interactive\System.Interactive.csproj", "{2EC0C302-B029-4DDB-AC91-000BF11006AD}"
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive.Providers", "refs\System.Interactive.Providers.Ref\System.Interactive.Providers.csproj", "{5DF341BE-B369-4250-AFD4-604DE8C95E45}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Interactive.Providers", "refs\System.Interactive.Providers\System.Interactive.Providers.csproj", "{5DF341BE-B369-4250-AFD4-604DE8C95E45}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks.System.Interactive", "Benchmarks.System.Interactive\Benchmarks.System.Interactive.csproj", "{3285529A-8227-4D40-B524-1A1F919F0E7B}"
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Linq.Async", "refs\System.Linq.Async.Ref\System.Linq.Async.csproj", "{1754B36C-D0DB-4E5D-8C30-1F116046DC0F}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Linq.Async", "refs\System.Linq.Async\System.Linq.Async.csproj", "{1754B36C-D0DB-4E5D-8C30-1F116046DC0F}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Linq.Async.SourceGenerator", "System.Linq.Async.SourceGenerator\System.Linq.Async.SourceGenerator.csproj", "{5C26D649-5ED4-49EE-AFBD-8FA8F12C4AE4}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.System.Interactive.ApiApprovals", "Tests.System.Interactive.ApiApprovals\Tests.System.Interactive.ApiApprovals.csproj", "{CD146918-6465-4D5B-B6B7-3F9803095EBD}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -134,13 +147,15 @@ Global
 		{3285529A-8227-4D40-B524-1A1F919F0E7B}.Release|Any CPU.ActiveCfg = Current Sources|Any CPU
 		{3285529A-8227-4D40-B524-1A1F919F0E7B}.Release|Any CPU.Build.0 = Current Sources|Any CPU
 		{1754B36C-D0DB-4E5D-8C30-1F116046DC0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{1754B36C-D0DB-4E5D-8C30-1F116046DC0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{1754B36C-D0DB-4E5D-8C30-1F116046DC0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{1754B36C-D0DB-4E5D-8C30-1F116046DC0F}.Release|Any CPU.Build.0 = Release|Any CPU
 		{5C26D649-5ED4-49EE-AFBD-8FA8F12C4AE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{5C26D649-5ED4-49EE-AFBD-8FA8F12C4AE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{5C26D649-5ED4-49EE-AFBD-8FA8F12C4AE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{5C26D649-5ED4-49EE-AFBD-8FA8F12C4AE4}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CD146918-6465-4D5B-B6B7-3F9803095EBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CD146918-6465-4D5B-B6B7-3F9803095EBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CD146918-6465-4D5B-B6B7-3F9803095EBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CD146918-6465-4D5B-B6B7-3F9803095EBD}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -164,6 +179,7 @@ Global
 		{5DF341BE-B369-4250-AFD4-604DE8C95E45} = {A3D72E6E-4ADA-42E0-8B2A-055B1F244281}
 		{1754B36C-D0DB-4E5D-8C30-1F116046DC0F} = {A3D72E6E-4ADA-42E0-8B2A-055B1F244281}
 		{5C26D649-5ED4-49EE-AFBD-8FA8F12C4AE4} = {80EFE3A1-1414-42EA-949B-1B5370A1B2EA}
+		{CD146918-6465-4D5B-B6B7-3F9803095EBD} = {87534290-A7A6-47A4-9A3A-D0D21A9AD1D4}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {AF70B0C6-C9D9-43B1-9BE4-08720EC1B7B7}

+ 7 - 0
Ix.NET/Source/NetCore31TestReadme.txt

@@ -0,0 +1,7 @@
+The tests all include a .NET Core 3.1 target, even though that has long since been out of support.
+
+The reason for this is that Ix.NET 6.0 offers a .NET Standard 2.1 target, and currently, the only way we have of testing this is through .NET Core 3.1.
+
+Although current versions of .NET (but not .NET Framework) support .NET Standard 2.1, they are all going to prefer the net6.0 target. We do test on currently supported versions of .NET, but we also want to test the .NET Standard 2.1 target.
+
+It might be possible to test via Mono instead, or possibly even Unity, but this would likely involve additional CI/CD work, so for now we're sticking with the .NET Core 3.1 target framework. It's unsupported, but it's better than doing no testing at all.

+ 3 - 9
Ix.NET/Source/Playground/DemoAttribute.cs

@@ -7,15 +7,9 @@ using System;
 namespace Playground
 {
     [AttributeUsage(AttributeTargets.Method)]
-    internal sealed class DemoAttribute : Attribute
+    internal sealed class DemoAttribute(int index, string title) : Attribute
     {
-        public DemoAttribute(int index, string title)
-        {
-            Index = index;
-            Title = title;
-        }
-
-        public int Index { get; }
-        public string Title { get; }
+        public int Index { get; } = index;
+        public string Title { get; } = title;
     }
 }

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

@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net8.0</TargetFramework>
   </PropertyGroup>
 
   <ItemGroup>

+ 15 - 13
Ix.NET/Source/Playground/Program.cs

@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT License.
 // See the LICENSE file in the project root for more information. 
 
+#pragma warning disable IDE0051 // Remove unused private members - all used via reflection
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -10,22 +12,22 @@ using System.Threading.Tasks;
 
 namespace Playground
 {
-    class Program
+    internal class Program
     {
-        static void Main()
+        private static void Main()
         {
             RunDemos();
         }
 
         [Demo(0, "Random experimentation")]
-        static async Task Experiment()
+        private static async Task Experiment()
         {
             // Add test code here
             await Task.Yield(); // Suppress CS1998
         }
 
         [Demo(11, "LINQ to Objects for IEnumerable<T>")]
-        static void Linq()
+        private static void Linq()
         {
             var xs = new List<int> { 1, 2, 3 };
             var ys = xs.Where(x => x % 2 == 0);
@@ -37,7 +39,7 @@ namespace Playground
         }
 
         [Demo(12, "LINQ to Objects for IQueryable<T>")]
-        static void LinqQueryable()
+        private static void LinqQueryable()
         {
             var xs = new List<int> { 1, 2, 3 }.AsQueryable();
             var ys = xs.Where(x => x % 2 == 0);
@@ -49,7 +51,7 @@ namespace Playground
         }
 
         [Demo(21, "LINQ to Objects for IEnumerable<T> - Interactive Extensions")]
-        static void Ix()
+        private static void Ix()
         {
             var xs = new List<int> { 1, 2, 3 };
             var ys = xs.Distinct(x => x % 2);
@@ -61,7 +63,7 @@ namespace Playground
         }
 
         [Demo(22, "LINQ to Objects for IQueryable<T> - Interactive Extensions")]
-        static void IxQueryable()
+        private static void IxQueryable()
         {
             var xs = new List<int> { 1, 2, 3 }.AsQueryable();
             var ys = xs.Distinct(x => x % 2);
@@ -73,7 +75,7 @@ namespace Playground
         }
 
         [Demo(31, "LINQ to Objects for IAsyncEnumerable<T>")]
-        static async Task AsyncLinq()
+        private static async Task AsyncLinq()
         {
             var xs = new List<int> { 1, 2, 3 };
             var ys = xs.ToAsyncEnumerable().Where(x => x % 2 == 0);
@@ -103,7 +105,7 @@ namespace Playground
         }
 
         [Demo(32, "LINQ to Objects for IAsyncQueryable<T>")]
-        static async Task AsyncLinqQueryable()
+        private static async Task AsyncLinqQueryable()
         {
             var xs = new List<int> { 1, 2, 3 }.AsQueryable();
             var ys = xs.ToAsyncEnumerable().Where(x => x % 2 == 0);
@@ -133,7 +135,7 @@ namespace Playground
         }
 
         [Demo(41, "LINQ to Objects for IAsyncEnumerable<T> - Interactive Extensions")]
-        static async Task AsyncIx()
+        private static async Task AsyncIx()
         {
             var xs = new List<int> { 1, 2, 3 };
             var ys = xs.ToAsyncEnumerable().Distinct(x => x % 2);
@@ -152,7 +154,7 @@ namespace Playground
         }
 
         [Demo(42, "LINQ to Objects for IAsyncQueryable<T> - Interactive Extensions")]
-        static async Task AsyncIxQueryable()
+        private static async Task AsyncIxQueryable()
         {
             var xs = new List<int> { 1, 2, 3 }.AsQueryable();
             var ys = xs.ToAsyncEnumerable().Distinct(x => x % 2);
@@ -170,7 +172,7 @@ namespace Playground
 #endif
         }
 
-        static void RunDemos()
+        private static void RunDemos()
         {
             var methods = (from method in typeof(Program).GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
                            let demo = method.GetCustomAttribute<DemoAttribute>()
@@ -197,7 +199,7 @@ namespace Playground
                 while (retry)
                 {
                     Console.Write("Enter demo [C: Clear, X: Exit]: ");
-                    var input = Console.ReadLine().Trim().ToUpper();
+                    var input = Console.ReadLine()?.Trim().ToUpper();
 
                     switch (input)
                     {

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

@@ -1,7 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net6.0;netcoreapp3.1</TargetFrameworks>
+    <!-- See NetCore31TestReadme.txt for why we still use netcoreapp3.1 -->
+    <TargetFrameworks>net48;net8.0;net6.0;netcoreapp3.1</TargetFrameworks>
     <NoWarn>$(NoWarn);CS0618</NoWarn>
   </PropertyGroup>
 

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

@@ -21,4 +21,8 @@
     <Compile Update="System\Linq\AsyncQueryableEx.Generated.cs" DesignTime="True" AutoGen="True" DependentUpon="AsyncQueryableEx.Generated.tt" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
+  </ItemGroup>
+
 </Project>

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

@@ -16,7 +16,7 @@ namespace System.Linq
     {
         private static MethodInfo? s_Amb__TSource__2__0;
         
-        private static MethodInfo? Amb__TSource__2__0(Type TSource) =>
+        private static MethodInfo Amb__TSource__2__0(Type TSource) =>
             (s_Amb__TSource__2__0 ??
             (s_Amb__TSource__2__0 = new Func<IAsyncQueryable<object>, IAsyncEnumerable<object>, IAsyncQueryable<object>>(Amb<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -32,7 +32,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Buffer__TSource__2__0;
         
-        private static MethodInfo? Buffer__TSource__2__0(Type TSource) =>
+        private static MethodInfo Buffer__TSource__2__0(Type TSource) =>
             (s_Buffer__TSource__2__0 ??
             (s_Buffer__TSource__2__0 = new Func<IAsyncQueryable<object>, int, IAsyncQueryable<IList<object>>>(Buffer<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -46,7 +46,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Buffer__TSource__3__0;
         
-        private static MethodInfo? Buffer__TSource__3__0(Type TSource) =>
+        private static MethodInfo Buffer__TSource__3__0(Type TSource) =>
             (s_Buffer__TSource__3__0 ??
             (s_Buffer__TSource__3__0 = new Func<IAsyncQueryable<object>, int, int, IAsyncQueryable<IList<object>>>(Buffer<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -60,7 +60,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Catch__TSource__2__0;
         
-        private static MethodInfo? Catch__TSource__2__0(Type TSource) =>
+        private static MethodInfo Catch__TSource__2__0(Type TSource) =>
             (s_Catch__TSource__2__0 ??
             (s_Catch__TSource__2__0 = new Func<IAsyncQueryable<object>, IAsyncEnumerable<object>, IAsyncQueryable<object>>(Catch<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -76,7 +76,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Catch__TSource_TException__2__0;
         
-        private static MethodInfo? Catch__TSource_TException__2__0(Type TSource, Type TException) =>
+        private static MethodInfo Catch__TSource_TException__2__0(Type TSource, Type TException) =>
             (s_Catch__TSource_TException__2__0 ??
             (s_Catch__TSource_TException__2__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<IAsyncEnumerable<object>>>>, IAsyncQueryable<object>>(Catch<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TException);
 
@@ -92,7 +92,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Catch__TSource_TException__2__1;
         
-        private static MethodInfo? Catch__TSource_TException__2__1(Type TSource, Type TException) =>
+        private static MethodInfo Catch__TSource_TException__2__1(Type TSource, Type TException) =>
             (s_Catch__TSource_TException__2__1 ??
             (s_Catch__TSource_TException__2__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, IAsyncEnumerable<object>>>, IAsyncQueryable<object>>(Catch<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TException);
 
@@ -108,7 +108,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Catch__TSource_TException__2__2;
         
-        private static MethodInfo? Catch__TSource_TException__2__2(Type TSource, Type TException) =>
+        private static MethodInfo Catch__TSource_TException__2__2(Type TSource, Type TException) =>
             (s_Catch__TSource_TException__2__2 ??
             (s_Catch__TSource_TException__2__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<IAsyncEnumerable<object>>>>, IAsyncQueryable<object>>(Catch<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TException);
 
@@ -124,7 +124,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Concat__TSource__1__0;
         
-        private static MethodInfo? Concat__TSource__1__0(Type TSource) =>
+        private static MethodInfo Concat__TSource__1__0(Type TSource) =>
             (s_Concat__TSource__1__0 ??
             (s_Concat__TSource__1__0 = new Func<IAsyncQueryable<IAsyncEnumerable<object>>, IAsyncQueryable<object>>(Concat<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -138,7 +138,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Distinct__TSource_TKey__2__0;
         
-        private static MethodInfo? Distinct__TSource_TKey__2__0(Type TSource, Type TKey) =>
+        private static MethodInfo Distinct__TSource_TKey__2__0(Type TSource, Type TKey) =>
             (s_Distinct__TSource_TKey__2__0 ??
             (s_Distinct__TSource_TKey__2__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, IAsyncQueryable<object>>(Distinct<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -154,7 +154,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Distinct__TSource_TKey__2__1;
         
-        private static MethodInfo? Distinct__TSource_TKey__2__1(Type TSource, Type TKey) =>
+        private static MethodInfo Distinct__TSource_TKey__2__1(Type TSource, Type TKey) =>
             (s_Distinct__TSource_TKey__2__1 ??
             (s_Distinct__TSource_TKey__2__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, IAsyncQueryable<object>>(Distinct<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -170,7 +170,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Distinct__TSource_TKey__2__2;
         
-        private static MethodInfo? Distinct__TSource_TKey__2__2(Type TSource, Type TKey) =>
+        private static MethodInfo Distinct__TSource_TKey__2__2(Type TSource, Type TKey) =>
             (s_Distinct__TSource_TKey__2__2 ??
             (s_Distinct__TSource_TKey__2__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, IAsyncQueryable<object>>(Distinct<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -186,7 +186,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Distinct__TSource_TKey__3__0;
         
-        private static MethodInfo? Distinct__TSource_TKey__3__0(Type TSource, Type TKey) =>
+        private static MethodInfo Distinct__TSource_TKey__3__0(Type TSource, Type TKey) =>
             (s_Distinct__TSource_TKey__3__0 ??
             (s_Distinct__TSource_TKey__3__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, IEqualityComparer<object>, IAsyncQueryable<object>>(Distinct<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -202,7 +202,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Distinct__TSource_TKey__3__1;
         
-        private static MethodInfo? Distinct__TSource_TKey__3__1(Type TSource, Type TKey) =>
+        private static MethodInfo Distinct__TSource_TKey__3__1(Type TSource, Type TKey) =>
             (s_Distinct__TSource_TKey__3__1 ??
             (s_Distinct__TSource_TKey__3__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, IEqualityComparer<object>, IAsyncQueryable<object>>(Distinct<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -218,7 +218,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Distinct__TSource_TKey__3__2;
         
-        private static MethodInfo? Distinct__TSource_TKey__3__2(Type TSource, Type TKey) =>
+        private static MethodInfo Distinct__TSource_TKey__3__2(Type TSource, Type TKey) =>
             (s_Distinct__TSource_TKey__3__2 ??
             (s_Distinct__TSource_TKey__3__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, IEqualityComparer<object>, IAsyncQueryable<object>>(Distinct<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -234,7 +234,7 @@ namespace System.Linq
 
         private static MethodInfo? s_DistinctUntilChanged__TSource__1__0;
         
-        private static MethodInfo? DistinctUntilChanged__TSource__1__0(Type TSource) =>
+        private static MethodInfo DistinctUntilChanged__TSource__1__0(Type TSource) =>
             (s_DistinctUntilChanged__TSource__1__0 ??
             (s_DistinctUntilChanged__TSource__1__0 = new Func<IAsyncQueryable<object>, IAsyncQueryable<object>>(DistinctUntilChanged<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -248,7 +248,7 @@ namespace System.Linq
 
         private static MethodInfo? s_DistinctUntilChanged__TSource__2__0;
         
-        private static MethodInfo? DistinctUntilChanged__TSource__2__0(Type TSource) =>
+        private static MethodInfo DistinctUntilChanged__TSource__2__0(Type TSource) =>
             (s_DistinctUntilChanged__TSource__2__0 ??
             (s_DistinctUntilChanged__TSource__2__0 = new Func<IAsyncQueryable<object>, IEqualityComparer<object>, IAsyncQueryable<object>>(DistinctUntilChanged<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -262,7 +262,7 @@ namespace System.Linq
 
         private static MethodInfo? s_DistinctUntilChanged__TSource_TKey__2__0;
         
-        private static MethodInfo? DistinctUntilChanged__TSource_TKey__2__0(Type TSource, Type TKey) =>
+        private static MethodInfo DistinctUntilChanged__TSource_TKey__2__0(Type TSource, Type TKey) =>
             (s_DistinctUntilChanged__TSource_TKey__2__0 ??
             (s_DistinctUntilChanged__TSource_TKey__2__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, IAsyncQueryable<object>>(DistinctUntilChanged<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -278,7 +278,7 @@ namespace System.Linq
 
         private static MethodInfo? s_DistinctUntilChanged__TSource_TKey__2__1;
         
-        private static MethodInfo? DistinctUntilChanged__TSource_TKey__2__1(Type TSource, Type TKey) =>
+        private static MethodInfo DistinctUntilChanged__TSource_TKey__2__1(Type TSource, Type TKey) =>
             (s_DistinctUntilChanged__TSource_TKey__2__1 ??
             (s_DistinctUntilChanged__TSource_TKey__2__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, IAsyncQueryable<object>>(DistinctUntilChanged<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -294,7 +294,7 @@ namespace System.Linq
 
         private static MethodInfo? s_DistinctUntilChanged__TSource_TKey__2__2;
         
-        private static MethodInfo? DistinctUntilChanged__TSource_TKey__2__2(Type TSource, Type TKey) =>
+        private static MethodInfo DistinctUntilChanged__TSource_TKey__2__2(Type TSource, Type TKey) =>
             (s_DistinctUntilChanged__TSource_TKey__2__2 ??
             (s_DistinctUntilChanged__TSource_TKey__2__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, IAsyncQueryable<object>>(DistinctUntilChanged<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -310,7 +310,7 @@ namespace System.Linq
 
         private static MethodInfo? s_DistinctUntilChanged__TSource_TKey__3__0;
         
-        private static MethodInfo? DistinctUntilChanged__TSource_TKey__3__0(Type TSource, Type TKey) =>
+        private static MethodInfo DistinctUntilChanged__TSource_TKey__3__0(Type TSource, Type TKey) =>
             (s_DistinctUntilChanged__TSource_TKey__3__0 ??
             (s_DistinctUntilChanged__TSource_TKey__3__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, IEqualityComparer<object>, IAsyncQueryable<object>>(DistinctUntilChanged<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -326,7 +326,7 @@ namespace System.Linq
 
         private static MethodInfo? s_DistinctUntilChanged__TSource_TKey__3__1;
         
-        private static MethodInfo? DistinctUntilChanged__TSource_TKey__3__1(Type TSource, Type TKey) =>
+        private static MethodInfo DistinctUntilChanged__TSource_TKey__3__1(Type TSource, Type TKey) =>
             (s_DistinctUntilChanged__TSource_TKey__3__1 ??
             (s_DistinctUntilChanged__TSource_TKey__3__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, IEqualityComparer<object>, IAsyncQueryable<object>>(DistinctUntilChanged<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -342,7 +342,7 @@ namespace System.Linq
 
         private static MethodInfo? s_DistinctUntilChanged__TSource_TKey__3__2;
         
-        private static MethodInfo? DistinctUntilChanged__TSource_TKey__3__2(Type TSource, Type TKey) =>
+        private static MethodInfo DistinctUntilChanged__TSource_TKey__3__2(Type TSource, Type TKey) =>
             (s_DistinctUntilChanged__TSource_TKey__3__2 ??
             (s_DistinctUntilChanged__TSource_TKey__3__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, IEqualityComparer<object>, IAsyncQueryable<object>>(DistinctUntilChanged<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -358,7 +358,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__2__0;
         
-        private static MethodInfo? Do__TSource__2__0(Type TSource) =>
+        private static MethodInfo Do__TSource__2__0(Type TSource) =>
             (s_Do__TSource__2__0 ??
             (s_Do__TSource__2__0 = new Func<IAsyncQueryable<object>, Expression<Action<object>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -374,7 +374,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__2__1;
         
-        private static MethodInfo? Do__TSource__2__1(Type TSource) =>
+        private static MethodInfo Do__TSource__2__1(Type TSource) =>
             (s_Do__TSource__2__1 ??
             (s_Do__TSource__2__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -390,7 +390,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__2__2;
         
-        private static MethodInfo? Do__TSource__2__2(Type TSource) =>
+        private static MethodInfo Do__TSource__2__2(Type TSource) =>
             (s_Do__TSource__2__2 ??
             (s_Do__TSource__2__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -406,7 +406,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__2__3;
         
-        private static MethodInfo? Do__TSource__2__3(Type TSource) =>
+        private static MethodInfo Do__TSource__2__3(Type TSource) =>
             (s_Do__TSource__2__3 ??
             (s_Do__TSource__2__3 = new Func<IAsyncQueryable<object>, IObserver<object>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -422,7 +422,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__3__0;
         
-        private static MethodInfo? Do__TSource__3__0(Type TSource) =>
+        private static MethodInfo Do__TSource__3__0(Type TSource) =>
             (s_Do__TSource__3__0 ??
             (s_Do__TSource__3__0 = new Func<IAsyncQueryable<object>, Expression<Action<object>>, Action, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -440,7 +440,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__3__1;
         
-        private static MethodInfo? Do__TSource__3__1(Type TSource) =>
+        private static MethodInfo Do__TSource__3__1(Type TSource) =>
             (s_Do__TSource__3__1 ??
             (s_Do__TSource__3__1 = new Func<IAsyncQueryable<object>, Expression<Action<object>>, Expression<Action<Exception>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -458,7 +458,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__3__2;
         
-        private static MethodInfo? Do__TSource__3__2(Type TSource) =>
+        private static MethodInfo Do__TSource__3__2(Type TSource) =>
             (s_Do__TSource__3__2 ??
             (s_Do__TSource__3__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, Task>>, Expression<Func<CancellationToken, Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -476,7 +476,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__3__3;
         
-        private static MethodInfo? Do__TSource__3__3(Type TSource) =>
+        private static MethodInfo Do__TSource__3__3(Type TSource) =>
             (s_Do__TSource__3__3 ??
             (s_Do__TSource__3__3 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, Task>>, Expression<Func<Exception, CancellationToken, Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -494,7 +494,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__3__4;
         
-        private static MethodInfo? Do__TSource__3__4(Type TSource) =>
+        private static MethodInfo Do__TSource__3__4(Type TSource) =>
             (s_Do__TSource__3__4 ??
             (s_Do__TSource__3__4 = new Func<IAsyncQueryable<object>, Expression<Func<object, Task>>, Expression<Func<Exception, Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -512,7 +512,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__3__5;
         
-        private static MethodInfo? Do__TSource__3__5(Type TSource) =>
+        private static MethodInfo Do__TSource__3__5(Type TSource) =>
             (s_Do__TSource__3__5 ??
             (s_Do__TSource__3__5 = new Func<IAsyncQueryable<object>, Expression<Func<object, Task>>, Expression<Func<Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -530,7 +530,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__4__0;
         
-        private static MethodInfo? Do__TSource__4__0(Type TSource) =>
+        private static MethodInfo Do__TSource__4__0(Type TSource) =>
             (s_Do__TSource__4__0 ??
             (s_Do__TSource__4__0 = new Func<IAsyncQueryable<object>, Expression<Action<object>>, Expression<Action<Exception>>, Action, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -550,7 +550,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__4__1;
         
-        private static MethodInfo? Do__TSource__4__1(Type TSource) =>
+        private static MethodInfo Do__TSource__4__1(Type TSource) =>
             (s_Do__TSource__4__1 ??
             (s_Do__TSource__4__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, Task>>, Expression<Func<Exception, CancellationToken, Task>>, Expression<Func<CancellationToken, Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -570,7 +570,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Do__TSource__4__2;
         
-        private static MethodInfo? Do__TSource__4__2(Type TSource) =>
+        private static MethodInfo Do__TSource__4__2(Type TSource) =>
             (s_Do__TSource__4__2 ??
             (s_Do__TSource__4__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, Task>>, Expression<Func<Exception, Task>>, Expression<Func<Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -590,7 +590,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Expand__TSource__2__0;
         
-        private static MethodInfo? Expand__TSource__2__0(Type TSource) =>
+        private static MethodInfo Expand__TSource__2__0(Type TSource) =>
             (s_Expand__TSource__2__0 ??
             (s_Expand__TSource__2__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<IAsyncEnumerable<object>>>>, IAsyncQueryable<object>>(Expand<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -606,7 +606,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Expand__TSource__2__1;
         
-        private static MethodInfo? Expand__TSource__2__1(Type TSource) =>
+        private static MethodInfo Expand__TSource__2__1(Type TSource) =>
             (s_Expand__TSource__2__1 ??
             (s_Expand__TSource__2__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, IAsyncEnumerable<object>>>, IAsyncQueryable<object>>(Expand<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -622,7 +622,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Expand__TSource__2__2;
         
-        private static MethodInfo? Expand__TSource__2__2(Type TSource) =>
+        private static MethodInfo Expand__TSource__2__2(Type TSource) =>
             (s_Expand__TSource__2__2 ??
             (s_Expand__TSource__2__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<IAsyncEnumerable<object>>>>, IAsyncQueryable<object>>(Expand<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -638,7 +638,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Finally__TSource__2__0;
         
-        private static MethodInfo? Finally__TSource__2__0(Type TSource) =>
+        private static MethodInfo Finally__TSource__2__0(Type TSource) =>
             (s_Finally__TSource__2__0 ??
             (s_Finally__TSource__2__0 = new Func<IAsyncQueryable<object>, Action, IAsyncQueryable<object>>(Finally<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -654,7 +654,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Finally__TSource__2__1;
         
-        private static MethodInfo? Finally__TSource__2__1(Type TSource) =>
+        private static MethodInfo Finally__TSource__2__1(Type TSource) =>
             (s_Finally__TSource__2__1 ??
             (s_Finally__TSource__2__1 = new Func<IAsyncQueryable<object>, Expression<Func<Task>>, IAsyncQueryable<object>>(Finally<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -670,7 +670,7 @@ namespace System.Linq
 
         private static MethodInfo? s_IgnoreElements__TSource__1__0;
         
-        private static MethodInfo? IgnoreElements__TSource__1__0(Type TSource) =>
+        private static MethodInfo IgnoreElements__TSource__1__0(Type TSource) =>
             (s_IgnoreElements__TSource__1__0 ??
             (s_IgnoreElements__TSource__1__0 = new Func<IAsyncQueryable<object>, IAsyncQueryable<object>>(IgnoreElements<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -684,7 +684,7 @@ namespace System.Linq
 
         private static MethodInfo? s_IsEmptyAsync__TSource__2__0;
         
-        private static MethodInfo? IsEmptyAsync__TSource__2__0(Type TSource) =>
+        private static MethodInfo IsEmptyAsync__TSource__2__0(Type TSource) =>
             (s_IsEmptyAsync__TSource__2__0 ??
             (s_IsEmptyAsync__TSource__2__0 = new Func<IAsyncQueryable<object>, CancellationToken, ValueTask<bool>>(IsEmptyAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -698,7 +698,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MaxAsync__TSource__3__0;
         
-        private static MethodInfo? MaxAsync__TSource__3__0(Type TSource) =>
+        private static MethodInfo MaxAsync__TSource__3__0(Type TSource) =>
             (s_MaxAsync__TSource__3__0 ??
             (s_MaxAsync__TSource__3__0 = new Func<IAsyncQueryable<object>, IComparer<object>, CancellationToken, ValueTask<object>>(MaxAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -712,7 +712,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MaxByAsync__TSource_TKey__3__0;
         
-        private static MethodInfo? MaxByAsync__TSource_TKey__3__0(Type TSource, Type TKey) =>
+        private static MethodInfo MaxByAsync__TSource_TKey__3__0(Type TSource, Type TKey) =>
             (s_MaxByAsync__TSource_TKey__3__0 ??
             (s_MaxByAsync__TSource_TKey__3__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, CancellationToken, ValueTask<IList<object>>>(MaxByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -728,7 +728,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MaxByAsync__TSource_TKey__3__1;
         
-        private static MethodInfo? MaxByAsync__TSource_TKey__3__1(Type TSource, Type TKey) =>
+        private static MethodInfo MaxByAsync__TSource_TKey__3__1(Type TSource, Type TKey) =>
             (s_MaxByAsync__TSource_TKey__3__1 ??
             (s_MaxByAsync__TSource_TKey__3__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, CancellationToken, ValueTask<IList<object>>>(MaxByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -744,7 +744,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MaxByAsync__TSource_TKey__3__2;
         
-        private static MethodInfo? MaxByAsync__TSource_TKey__3__2(Type TSource, Type TKey) =>
+        private static MethodInfo MaxByAsync__TSource_TKey__3__2(Type TSource, Type TKey) =>
             (s_MaxByAsync__TSource_TKey__3__2 ??
             (s_MaxByAsync__TSource_TKey__3__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, CancellationToken, ValueTask<IList<object>>>(MaxByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -760,7 +760,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MaxByAsync__TSource_TKey__4__0;
         
-        private static MethodInfo? MaxByAsync__TSource_TKey__4__0(Type TSource, Type TKey) =>
+        private static MethodInfo MaxByAsync__TSource_TKey__4__0(Type TSource, Type TKey) =>
             (s_MaxByAsync__TSource_TKey__4__0 ??
             (s_MaxByAsync__TSource_TKey__4__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MaxByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -776,7 +776,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MaxByAsync__TSource_TKey__4__1;
         
-        private static MethodInfo? MaxByAsync__TSource_TKey__4__1(Type TSource, Type TKey) =>
+        private static MethodInfo MaxByAsync__TSource_TKey__4__1(Type TSource, Type TKey) =>
             (s_MaxByAsync__TSource_TKey__4__1 ??
             (s_MaxByAsync__TSource_TKey__4__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MaxByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -792,7 +792,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MaxByAsync__TSource_TKey__4__2;
         
-        private static MethodInfo? MaxByAsync__TSource_TKey__4__2(Type TSource, Type TKey) =>
+        private static MethodInfo MaxByAsync__TSource_TKey__4__2(Type TSource, Type TKey) =>
             (s_MaxByAsync__TSource_TKey__4__2 ??
             (s_MaxByAsync__TSource_TKey__4__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MaxByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -808,7 +808,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Merge__TSource__1__0;
         
-        private static MethodInfo? Merge__TSource__1__0(Type TSource) =>
+        private static MethodInfo Merge__TSource__1__0(Type TSource) =>
             (s_Merge__TSource__1__0 ??
             (s_Merge__TSource__1__0 = new Func<IAsyncQueryable<IAsyncEnumerable<object>>, IAsyncQueryable<object>>(Merge<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -822,7 +822,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MinAsync__TSource__3__0;
         
-        private static MethodInfo? MinAsync__TSource__3__0(Type TSource) =>
+        private static MethodInfo MinAsync__TSource__3__0(Type TSource) =>
             (s_MinAsync__TSource__3__0 ??
             (s_MinAsync__TSource__3__0 = new Func<IAsyncQueryable<object>, IComparer<object>, CancellationToken, ValueTask<object>>(MinAsync<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -836,7 +836,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MinByAsync__TSource_TKey__3__0;
         
-        private static MethodInfo? MinByAsync__TSource_TKey__3__0(Type TSource, Type TKey) =>
+        private static MethodInfo MinByAsync__TSource_TKey__3__0(Type TSource, Type TKey) =>
             (s_MinByAsync__TSource_TKey__3__0 ??
             (s_MinByAsync__TSource_TKey__3__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, CancellationToken, ValueTask<IList<object>>>(MinByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -852,7 +852,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MinByAsync__TSource_TKey__3__1;
         
-        private static MethodInfo? MinByAsync__TSource_TKey__3__1(Type TSource, Type TKey) =>
+        private static MethodInfo MinByAsync__TSource_TKey__3__1(Type TSource, Type TKey) =>
             (s_MinByAsync__TSource_TKey__3__1 ??
             (s_MinByAsync__TSource_TKey__3__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, CancellationToken, ValueTask<IList<object>>>(MinByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -868,7 +868,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MinByAsync__TSource_TKey__3__2;
         
-        private static MethodInfo? MinByAsync__TSource_TKey__3__2(Type TSource, Type TKey) =>
+        private static MethodInfo MinByAsync__TSource_TKey__3__2(Type TSource, Type TKey) =>
             (s_MinByAsync__TSource_TKey__3__2 ??
             (s_MinByAsync__TSource_TKey__3__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, CancellationToken, ValueTask<IList<object>>>(MinByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -884,7 +884,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MinByAsync__TSource_TKey__4__0;
         
-        private static MethodInfo? MinByAsync__TSource_TKey__4__0(Type TSource, Type TKey) =>
+        private static MethodInfo MinByAsync__TSource_TKey__4__0(Type TSource, Type TKey) =>
             (s_MinByAsync__TSource_TKey__4__0 ??
             (s_MinByAsync__TSource_TKey__4__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<object>>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MinByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -900,7 +900,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MinByAsync__TSource_TKey__4__1;
         
-        private static MethodInfo? MinByAsync__TSource_TKey__4__1(Type TSource, Type TKey) =>
+        private static MethodInfo MinByAsync__TSource_TKey__4__1(Type TSource, Type TKey) =>
             (s_MinByAsync__TSource_TKey__4__1 ??
             (s_MinByAsync__TSource_TKey__4__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MinByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -916,7 +916,7 @@ namespace System.Linq
 
         private static MethodInfo? s_MinByAsync__TSource_TKey__4__2;
         
-        private static MethodInfo? MinByAsync__TSource_TKey__4__2(Type TSource, Type TKey) =>
+        private static MethodInfo MinByAsync__TSource_TKey__4__2(Type TSource, Type TKey) =>
             (s_MinByAsync__TSource_TKey__4__2 ??
             (s_MinByAsync__TSource_TKey__4__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, ValueTask<object>>>, IComparer<object>, CancellationToken, ValueTask<IList<object>>>(MinByAsync<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TKey);
 
@@ -932,7 +932,7 @@ namespace System.Linq
 
         private static MethodInfo? s_OnErrorResumeNext__TSource__2__0;
         
-        private static MethodInfo? OnErrorResumeNext__TSource__2__0(Type TSource) =>
+        private static MethodInfo OnErrorResumeNext__TSource__2__0(Type TSource) =>
             (s_OnErrorResumeNext__TSource__2__0 ??
             (s_OnErrorResumeNext__TSource__2__0 = new Func<IAsyncQueryable<object>, IAsyncEnumerable<object>, IAsyncQueryable<object>>(OnErrorResumeNext<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -948,7 +948,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Repeat__TSource__1__0;
         
-        private static MethodInfo? Repeat__TSource__1__0(Type TSource) =>
+        private static MethodInfo Repeat__TSource__1__0(Type TSource) =>
             (s_Repeat__TSource__1__0 ??
             (s_Repeat__TSource__1__0 = new Func<IAsyncQueryable<object>, IAsyncQueryable<object>>(Repeat<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -962,7 +962,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Repeat__TSource__2__0;
         
-        private static MethodInfo? Repeat__TSource__2__0(Type TSource) =>
+        private static MethodInfo Repeat__TSource__2__0(Type TSource) =>
             (s_Repeat__TSource__2__0 ??
             (s_Repeat__TSource__2__0 = new Func<IAsyncQueryable<object>, int, IAsyncQueryable<object>>(Repeat<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -976,7 +976,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Retry__TSource__1__0;
         
-        private static MethodInfo? Retry__TSource__1__0(Type TSource) =>
+        private static MethodInfo Retry__TSource__1__0(Type TSource) =>
             (s_Retry__TSource__1__0 ??
             (s_Retry__TSource__1__0 = new Func<IAsyncQueryable<object>, IAsyncQueryable<object>>(Retry<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -990,7 +990,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Retry__TSource__2__0;
         
-        private static MethodInfo? Retry__TSource__2__0(Type TSource) =>
+        private static MethodInfo Retry__TSource__2__0(Type TSource) =>
             (s_Retry__TSource__2__0 ??
             (s_Retry__TSource__2__0 = new Func<IAsyncQueryable<object>, int, IAsyncQueryable<object>>(Retry<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -1004,7 +1004,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Scan__TSource__2__0;
         
-        private static MethodInfo? Scan__TSource__2__0(Type TSource) =>
+        private static MethodInfo Scan__TSource__2__0(Type TSource) =>
             (s_Scan__TSource__2__0 ??
             (s_Scan__TSource__2__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, object, CancellationToken, ValueTask<object>>>, IAsyncQueryable<object>>(Scan<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -1020,7 +1020,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Scan__TSource__2__1;
         
-        private static MethodInfo? Scan__TSource__2__1(Type TSource) =>
+        private static MethodInfo Scan__TSource__2__1(Type TSource) =>
             (s_Scan__TSource__2__1 ??
             (s_Scan__TSource__2__1 = new Func<IAsyncQueryable<object>, Expression<Func<object, object, object>>, IAsyncQueryable<object>>(Scan<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -1036,7 +1036,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Scan__TSource__2__2;
         
-        private static MethodInfo? Scan__TSource__2__2(Type TSource) =>
+        private static MethodInfo Scan__TSource__2__2(Type TSource) =>
             (s_Scan__TSource__2__2 ??
             (s_Scan__TSource__2__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, object, ValueTask<object>>>, IAsyncQueryable<object>>(Scan<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -1052,7 +1052,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Scan__TSource_TAccumulate__3__0;
         
-        private static MethodInfo? Scan__TSource_TAccumulate__3__0(Type TSource, Type TAccumulate) =>
+        private static MethodInfo Scan__TSource_TAccumulate__3__0(Type TSource, Type TAccumulate) =>
             (s_Scan__TSource_TAccumulate__3__0 ??
             (s_Scan__TSource_TAccumulate__3__0 = new Func<IAsyncQueryable<object>, object, Expression<Func<object, object, CancellationToken, ValueTask<object>>>, IAsyncQueryable<object>>(Scan<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TAccumulate);
 
@@ -1068,7 +1068,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Scan__TSource_TAccumulate__3__1;
         
-        private static MethodInfo? Scan__TSource_TAccumulate__3__1(Type TSource, Type TAccumulate) =>
+        private static MethodInfo Scan__TSource_TAccumulate__3__1(Type TSource, Type TAccumulate) =>
             (s_Scan__TSource_TAccumulate__3__1 ??
             (s_Scan__TSource_TAccumulate__3__1 = new Func<IAsyncQueryable<object>, object, Expression<Func<object, object, object>>, IAsyncQueryable<object>>(Scan<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TAccumulate);
 
@@ -1084,7 +1084,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Scan__TSource_TAccumulate__3__2;
         
-        private static MethodInfo? Scan__TSource_TAccumulate__3__2(Type TSource, Type TAccumulate) =>
+        private static MethodInfo Scan__TSource_TAccumulate__3__2(Type TSource, Type TAccumulate) =>
             (s_Scan__TSource_TAccumulate__3__2 ??
             (s_Scan__TSource_TAccumulate__3__2 = new Func<IAsyncQueryable<object>, object, Expression<Func<object, object, ValueTask<object>>>, IAsyncQueryable<object>>(Scan<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TAccumulate);
 
@@ -1100,7 +1100,7 @@ namespace System.Linq
 
         private static MethodInfo? s_SelectMany__TSource_TOther__2__0;
         
-        private static MethodInfo? SelectMany__TSource_TOther__2__0(Type TSource, Type TOther) =>
+        private static MethodInfo SelectMany__TSource_TOther__2__0(Type TSource, Type TOther) =>
             (s_SelectMany__TSource_TOther__2__0 ??
             (s_SelectMany__TSource_TOther__2__0 = new Func<IAsyncQueryable<object>, IAsyncEnumerable<object>, IAsyncQueryable<object>>(SelectMany<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource, TOther);
 
@@ -1116,7 +1116,7 @@ namespace System.Linq
 
         private static MethodInfo? s_StartWith__TSource__2__0;
         
-        private static MethodInfo? StartWith__TSource__2__0(Type TSource) =>
+        private static MethodInfo StartWith__TSource__2__0(Type TSource) =>
             (s_StartWith__TSource__2__0 ??
             (s_StartWith__TSource__2__0 = new Func<IAsyncQueryable<object>, object[], IAsyncQueryable<object>>(StartWith<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 
@@ -1132,7 +1132,7 @@ namespace System.Linq
 
         private static MethodInfo? s_Timeout__TSource__2__0;
         
-        private static MethodInfo? Timeout__TSource__2__0(Type TSource) =>
+        private static MethodInfo Timeout__TSource__2__0(Type TSource) =>
             (s_Timeout__TSource__2__0 ??
             (s_Timeout__TSource__2__0 = new Func<IAsyncQueryable<object>, TimeSpan, IAsyncQueryable<object>>(Timeout<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
 

+ 4 - 4
Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.tt

@@ -3,10 +3,10 @@
 // See the LICENSE file in the project root for more information. 
 
 <#@ template debug="false" hostspecific="false" language="C#" #>
-<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net461\Microsoft.Bcl.AsyncInterfaces.dll" #>
-<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net461\System.Threading.Tasks.Extensions.dll" #>
-<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net461\System.Linq.Async.dll" #>
-<#@ assembly name="$(ProjectDir)\..\System.Interactive.Async\bin\$(Configuration)\net461\System.Interactive.Async.dll" #>
+<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net48\Microsoft.Bcl.AsyncInterfaces.dll" #>
+<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net48\System.Threading.Tasks.Extensions.dll" #>
+<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net48\System.Linq.Async.dll" #>
+<#@ assembly name="$(ProjectDir)\..\System.Interactive.Async\bin\$(Configuration)\net48\System.Interactive.Async.dll" #>
 <#@ output extension=".cs" #>
 <#
 var asyncEnumerableType = typeof(AsyncEnumerableEx);

+ 9 - 2
Ix.NET/Source/System.Interactive.Async.Tests/System.Interactive.Async.Tests.csproj

@@ -1,8 +1,15 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net6.0;netcoreapp3.1</TargetFrameworks>
-    <NoWarn>$(NoWarn);CS0618;CS8603;CS8625</NoWarn>
+    <!-- See NetCore31TestReadme.txt for why we still use netcoreapp3.1 -->
+    <TargetFrameworks>net48;net8.0;net6.0;netcoreapp3.1</TargetFrameworks>
+
+    <!--
+      CA1510: Use ArgumentNullException.ThrowIfNull - not available on .NET 4.8
+      CA1822: Make member static. Not necessary for test code.
+      CA1861: Extract constant arrays to 'static readonly' fields. With these tests we generally prioritize readability over performance.
+    -->
+    <NoWarn>$(NoWarn);CS0618;CS8603;CS8625;CA1510;CA1822;CA1861</NoWarn>
   </PropertyGroup>
 
   <ItemGroup>

+ 8 - 8
Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/Buffer.cs

@@ -31,13 +31,13 @@ namespace Tests
             var e = xs.GetAsyncEnumerator();
 
             Assert.True(await e.MoveNextAsync());
-            Assert.True(e.Current.SequenceEqual(new[] { 1, 2 }));
+            Assert.True(e.Current.SequenceEqual([1, 2]));
 
             Assert.True(await e.MoveNextAsync());
-            Assert.True(e.Current.SequenceEqual(new[] { 3, 4 }));
+            Assert.True(e.Current.SequenceEqual([3, 4]));
 
             Assert.True(await e.MoveNextAsync());
-            Assert.True(e.Current.SequenceEqual(new[] { 5 }));
+            Assert.True(e.Current.SequenceEqual([5]));
 
             Assert.False(await e.MoveNextAsync());
         }
@@ -50,13 +50,13 @@ namespace Tests
             var e = xs.GetAsyncEnumerator();
 
             Assert.True(await e.MoveNextAsync());
-            Assert.True(e.Current.SequenceEqual(new[] { 1, 2, 3 }));
+            Assert.True(e.Current.SequenceEqual([1, 2, 3]));
 
             Assert.True(await e.MoveNextAsync());
-            Assert.True(e.Current.SequenceEqual(new[] { 3, 4, 5 }));
+            Assert.True(e.Current.SequenceEqual([3, 4, 5]));
 
             Assert.True(await e.MoveNextAsync());
-            Assert.True(e.Current.SequenceEqual(new[] { 5 }));
+            Assert.True(e.Current.SequenceEqual([5]));
 
             Assert.False(await e.MoveNextAsync());
         }
@@ -69,10 +69,10 @@ namespace Tests
             var e = xs.GetAsyncEnumerator();
 
             Assert.True(await e.MoveNextAsync());
-            Assert.True(e.Current.SequenceEqual(new[] { 1, 2 }));
+            Assert.True(e.Current.SequenceEqual([1, 2]));
 
             Assert.True(await e.MoveNextAsync());
-            Assert.True(e.Current.SequenceEqual(new[] { 4, 5 }));
+            Assert.True(e.Current.SequenceEqual([4, 5]));
 
             Assert.False(await e.MoveNextAsync());
         }

+ 2 - 2
Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/MaxBy.cs

@@ -35,13 +35,13 @@ namespace Tests
             var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MaxByAsync(x => x / 2);
             var res = await xs;
 
-            Assert.True(res.SequenceEqual(new[] { 7, 6 }));
+            Assert.True(res.SequenceEqual([7, 6]));
         }
 
         [Fact]
         public async Task MaxBy2()
         {
-            var xs = new int[0].ToAsyncEnumerable().MaxByAsync(x => x / 2);
+            var xs = Array.Empty<int>().ToAsyncEnumerable().MaxByAsync(x => x / 2);
 
             await AssertThrowsAsync<InvalidOperationException>(xs.AsTask());
         }

+ 2 - 2
Ix.NET/Source/System.Interactive.Async.Tests/System/Linq/Operators/MinBy.cs

@@ -35,13 +35,13 @@ namespace Tests
             var xs = new[] { 3, 5, 7, 6, 4, 2 }.ToAsyncEnumerable().MinByAsync(x => x / 2);
             var res = await xs;
 
-            Assert.True(res.SequenceEqual(new[] { 3, 2 }));
+            Assert.True(res.SequenceEqual([3, 2]));
         }
 
         [Fact]
         public async Task MinBy2Async()
         {
-            var xs = new int[0].ToAsyncEnumerable().MinByAsync(x => x / 2);
+            var xs = Array.Empty<int>().ToAsyncEnumerable().MinByAsync(x => x / 2);
 
             await AssertThrowsAsync<InvalidOperationException>(xs.AsTask());
         }

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

@@ -2,6 +2,10 @@
 // The .NET Foundation licenses this file to you under the MIT License.
 // See the LICENSE file in the project root for more information. 
 
+#if NET6_0_OR_GREATER
+#pragma warning disable CA2012 // Use ValueTasks correctly. These tests need to use Result to verify correct operation, so we can't avoid breaking this rule.
+#endif
+
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;

+ 0 - 15
Ix.NET/Source/System.Interactive.Async/EmptyArray.cs

@@ -1,15 +0,0 @@
-// 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. 
-
-#if NO_ARRAY_EMPTY
-
-namespace System.Linq
-{
-    internal sealed class EmptyArray<TElement>
-    {
-        public static readonly TElement[] Value = new TElement[0];
-    }
-}
-
-#endif

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

@@ -7,6 +7,11 @@
     <PackageTags>Ix;Interactive;Extensions;Enumerable;Asynchronous</PackageTags>
   </PropertyGroup>
 
+  <PropertyGroup>
+    <!-- IDE0305 wants to turn things like list.ToArray into [..list], which we don't find to be an improvement in readability. -->
+    <NoWarn>$(NoWarn);IDE0305</NoWarn>
+  </PropertyGroup>
+
   <ItemGroup>
     <Compile Include="..\System.Linq.Async\System\Error.cs" Link="System\Error.cs" />
     <Compile Include="..\System.Linq.Async\System\Linq\AsyncIterator.cs" Link="System\Linq\AsyncIterator.cs" />

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

@@ -34,7 +34,7 @@ namespace System.Linq
 #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
             return Core(initialState, condition, iterate, resultSelector);
 
-            static async IAsyncEnumerable<TResult> Core(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
+            static async IAsyncEnumerable<TResult> Core(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
             {
                 for (var state = initialState; condition(state); state = iterate(state))
                 {

+ 16 - 15
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Merge.cs

@@ -276,12 +276,7 @@ namespace System.Linq
                         }
                         catch (Exception ex)
                         {
-                            if (errors == null)
-                            {
-                                errors = new List<Exception>();
-                            }
-
-                            errors.Add(ex);
+                            (errors ??= []).Add(ex);
                         }
                     }
 
@@ -292,21 +287,27 @@ namespace System.Linq
 
                     if (errors != null)
                     {
+#if NET6_0_OR_GREATER
+#pragma warning disable CA2219 // Do not raise an exception from within a finally clause
+#endif
                         throw new AggregateException(errors);
+#if NET6_0_OR_GREATER
+#pragma warning restore CA2219
+#endif
                     }
                 }
             }
 #endif
-        }
+                    }
 
-        /// <summary>
-        /// Merges elements from all async-enumerable sequences in the given enumerable sequence into a single async-enumerable sequence.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
-        /// <param name="sources">Enumerable sequence of async-enumerable sequences.</param>
-        /// <returns>The async-enumerable sequence that merges the elements of the async-enumerable sequences.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="sources"/> is null.</exception>
-        public static IAsyncEnumerable<TSource> Merge<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
+                    /// <summary>
+                    /// Merges elements from all async-enumerable sequences in the given enumerable sequence into a single async-enumerable sequence.
+                    /// </summary>
+                    /// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
+                    /// <param name="sources">Enumerable sequence of async-enumerable sequences.</param>
+                    /// <returns>The async-enumerable sequence that merges the elements of the async-enumerable sequences.</returns>
+                    /// <exception cref="ArgumentNullException"><paramref name="sources"/> is null.</exception>
+                    public static IAsyncEnumerable<TSource> Merge<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
         {
             if (sources == null)
                 throw Error.ArgumentNull(nameof(sources));

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

@@ -192,7 +192,7 @@ namespace System.Linq
                     }
                     else if (cmp > 0)
                     {
-                        result = new List<TSource> { cur };
+                        result = [cur];
                         resKey = key;
                     }
                 }
@@ -227,7 +227,7 @@ namespace System.Linq
                     }
                     else if (cmp > 0)
                     {
-                        result = new List<TSource> { cur };
+                        result = [cur];
                         resKey = key;
                     }
                 }
@@ -263,7 +263,7 @@ namespace System.Linq
                     }
                     else if (cmp > 0)
                     {
-                        result = new List<TSource> { cur };
+                        result = [cur];
                         resKey = key;
                     }
                 }

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

@@ -19,7 +19,7 @@ namespace System.Linq
 
         private sealed class NeverAsyncEnumerable<TValue> : IAsyncEnumerable<TValue>
         {
-            internal static readonly NeverAsyncEnumerable<TValue> Instance = new NeverAsyncEnumerable<TValue>();
+            internal static readonly NeverAsyncEnumerable<TValue> Instance = new();
 
             public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken)
             {
@@ -28,15 +28,13 @@ namespace System.Linq
                 return new NeverAsyncEnumerator(cancellationToken);
             }
 
-            private sealed class NeverAsyncEnumerator : IAsyncEnumerator<TValue>
+            private sealed class NeverAsyncEnumerator(CancellationToken token) : IAsyncEnumerator<TValue>
             {
-                private readonly CancellationToken _token;
+                private readonly CancellationToken _token = token;
 
                 private CancellationTokenRegistration _registration;
                 private bool _once;
 
-                public NeverAsyncEnumerator(CancellationToken token) => _token = token;
-
                 public TValue Current => throw new InvalidOperationException();
 
                 public ValueTask DisposeAsync()
@@ -54,7 +52,7 @@ namespace System.Linq
 
                     _once = true;
                     var task = new TaskCompletionSource<bool>();
-                    _registration = _token.Register(state => ((TaskCompletionSource<bool>)state).TrySetCanceled(_token), task);
+                    _registration = _token.Register(state => ((TaskCompletionSource<bool>)state!).TrySetCanceled(_token), task);
                     return new ValueTask<bool>(task.Task);
                 }
             }

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

@@ -33,11 +33,11 @@ namespace System.Linq
                 return new ReturnEnumerator(_value);
             }
 
-            public ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken) => new ValueTask<int>(1);
+            public ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken) => new(1);
 
-            public ValueTask<TValue[]> ToArrayAsync(CancellationToken cancellationToken) => new ValueTask<TValue[]>(new[] { _value });
+            public ValueTask<TValue[]> ToArrayAsync(CancellationToken cancellationToken) => new([_value]);
 
-            public ValueTask<List<TValue>> ToListAsync(CancellationToken cancellationToken) => new ValueTask<List<TValue>>(new List<TValue>(1) { _value });
+            public ValueTask<List<TValue>> ToListAsync(CancellationToken cancellationToken) => new([_value]);
 
             private sealed class ReturnEnumerator : IAsyncEnumerator<TValue>
             {

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

@@ -105,7 +105,13 @@ namespace System.Linq
                         goto case AsyncIteratorState.Iterating;
 
                     case AsyncIteratorState.Iterating:
+#if NET6_0_OR_GREATER
+#pragma warning disable CA2012 // Always await ValueTasks immediately; this is deliberate advanced usage
+#endif
                         var moveNext = _enumerator!.MoveNextAsync();
+#if NET6_0_OR_GREATER
+#pragma warning restore CA2012
+#endif
 
                         if (!moveNext.IsCompleted)
                         {

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

@@ -1,4 +1,4 @@
-<Project Sdk="MSBuild.Sdk.Extras">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <Description>Interactive Extensions Providers Library used to build query providers and express queries over enumerable sequences.</Description>
@@ -13,7 +13,32 @@
 
   <ItemGroup>
     <ProjectReference Include="..\System.Interactive\System.Interactive.csproj" />
-    <ReferenceAssemblyProjectReference Include="..\refs\System.Interactive.Providers.Ref\System.Interactive.Providers.csproj" ReferenceOutputAssembly="false" />
   </ItemGroup>
 
+  <!--
+  Incorporate the reference assemblies. Note that these have a different set of TFMs from the proper assemblies.
+  
+  See ../../Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md
+  -->
+  <ItemGroup>
+    <None Include="../refs/System.Interactive.Providers/bin/$(Configuration)/$(TargetFramework)/**"
+          PackagePath="ref/$(TargetFramework)"
+          Pack="true" />
+  </ItemGroup>
+
+  <!--
+  These warnings occur because we are deliberately creating a lib/ref mismatch. There doesn't seem to be
+  an official way to do that, so we have to suppress the warnings.
+  
+  See ../../Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md for an explanation of this bizarreness.
+  -->
+
+  <PropertyGroup>
+    <!--
+    NU5128: lib/ref mismatch. This is deliberate, as explained in the ADR.
+    NU5131: spurious missing file errors. It appears that the build is confused by what we're doing.
+    -->
+    <NoWarn>$(NoWarn);NU5128;NU5131</NoWarn>
+  </PropertyGroup>
+
 </Project>

+ 2 - 2
Ix.NET/Source/System.Interactive.Providers/System/Linq/QueryableEx.cs

@@ -23,7 +23,7 @@ namespace System.Linq
         {
             public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
             {
-                var provider = new TElement[0].AsQueryable().Provider;
+                var provider = Array.Empty<TElement>().AsQueryable().Provider;
                 var res = Redir(expression);
                 return provider.CreateQuery<TElement>(res);
             }
@@ -35,7 +35,7 @@ namespace System.Linq
 
             public TResult Execute<TResult>(Expression expression)
             {
-                var provider = new TResult[0].AsQueryable().Provider;
+                var provider = Array.Empty<TResult>().AsQueryable().Provider;
                 var res = Redir(expression);
                 return provider.Execute<TResult>(res);
             }

+ 8 - 2
Ix.NET/Source/System.Interactive.Tests/System.Interactive.Tests.csproj

@@ -1,8 +1,14 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net6.0;netcoreapp3.1</TargetFrameworks>
-    <NoWarn>$(NoWarn);CS0618;CS8603;CS8625</NoWarn>
+    <!-- See NetCore31TestReadme.txt for why we still use netcoreapp3.1 -->
+    <TargetFrameworks>net48;net8.0;net6.0;netcoreapp3.1</TargetFrameworks>
+
+    <!--
+      CA1822: Make member static. Not necessary for test code.
+      CA1861: Extract constant arrays to 'static readonly' fields. With these tests we generally prioritize readability over performance.
+    -->
+    <NoWarn>$(NoWarn);CS0618;CS8603;CS8625;CA1822;CA1861</NoWarn>
   </PropertyGroup>
 
   <ItemGroup>

+ 17 - 17
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Buffer.cs

@@ -15,9 +15,9 @@ namespace Tests
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Buffer<int>(null, 5));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Buffer<int>(null, 5, 3));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Buffer<int>(new[] { 1 }, 0));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Buffer<int>(new[] { 1 }, 5, 0));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Buffer<int>(new[] { 1 }, 0, 3));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Buffer<int>([1], 0));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Buffer<int>([1], 5, 0));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Buffer<int>([1], 0, 3));
         }
 
         [Fact]
@@ -28,10 +28,10 @@ namespace Tests
             var res = rng.Buffer(3).ToList();
             Assert.Equal(4, res.Count);
 
-            Assert.True(res[0].SequenceEqual(new[] { 0, 1, 2 }));
-            Assert.True(res[1].SequenceEqual(new[] { 3, 4, 5 }));
-            Assert.True(res[2].SequenceEqual(new[] { 6, 7, 8 }));
-            Assert.True(res[3].SequenceEqual(new[] { 9 }));
+            Assert.True(res[0].SequenceEqual([0, 1, 2]));
+            Assert.True(res[1].SequenceEqual([3, 4, 5]));
+            Assert.True(res[2].SequenceEqual([6, 7, 8]));
+            Assert.True(res[3].SequenceEqual([9]));
         }
 
         [Fact]
@@ -42,8 +42,8 @@ namespace Tests
             var res = rng.Buffer(5).ToList();
             Assert.Equal(2, res.Count);
 
-            Assert.True(res[0].SequenceEqual(new[] { 0, 1, 2, 3, 4 }));
-            Assert.True(res[1].SequenceEqual(new[] { 5, 6, 7, 8, 9 }));
+            Assert.True(res[0].SequenceEqual([0, 1, 2, 3, 4]));
+            Assert.True(res[1].SequenceEqual([5, 6, 7, 8, 9]));
         }
 
         [Fact]
@@ -63,11 +63,11 @@ namespace Tests
             var res = rng.Buffer(3, 2).ToList();
             Assert.Equal(5, res.Count);
 
-            Assert.True(res[0].SequenceEqual(new[] { 0, 1, 2 }));
-            Assert.True(res[1].SequenceEqual(new[] { 2, 3, 4 }));
-            Assert.True(res[2].SequenceEqual(new[] { 4, 5, 6 }));
-            Assert.True(res[3].SequenceEqual(new[] { 6, 7, 8 }));
-            Assert.True(res[4].SequenceEqual(new[] { 8, 9 }));
+            Assert.True(res[0].SequenceEqual([0, 1, 2]));
+            Assert.True(res[1].SequenceEqual([2, 3, 4]));
+            Assert.True(res[2].SequenceEqual([4, 5, 6]));
+            Assert.True(res[3].SequenceEqual([6, 7, 8]));
+            Assert.True(res[4].SequenceEqual([8, 9]));
         }
 
         [Fact]
@@ -78,9 +78,9 @@ namespace Tests
             var res = rng.Buffer(3, 4).ToList();
             Assert.Equal(3, res.Count);
 
-            Assert.True(res[0].SequenceEqual(new[] { 0, 1, 2 }));
-            Assert.True(res[1].SequenceEqual(new[] { 4, 5, 6 }));
-            Assert.True(res[2].SequenceEqual(new[] { 8, 9 }));
+            Assert.True(res[0].SequenceEqual([0, 1, 2]));
+            Assert.True(res[1].SequenceEqual([4, 5, 6]));
+            Assert.True(res[2].SequenceEqual([8, 9]));
         }
     }
 }

+ 3 - 3
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Case.cs

@@ -16,8 +16,8 @@ namespace Tests
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Case<int, int>(null, new Dictionary<int, IEnumerable<int>>()));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Case<int, int>(() => 1, null));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Case<int, int>(null, new Dictionary<int, IEnumerable<int>>(), new[] { 1 }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Case<int, int>(() => 1, null, new[] { 1 }));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Case<int, int>(null, new Dictionary<int, IEnumerable<int>>(), [1]));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Case<int, int>(() => 1, null, [1]));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Case<int, int>(() => 1, new Dictionary<int, IEnumerable<int>>(), null));
         }
 
@@ -64,7 +64,7 @@ namespace Tests
                 { 1, new[] { 'b' } },
                 { 2, new[] { 'c' } },
                 { 3, EnumerableEx.Defer(() => new[] { d }) },
-            }, new[] { 'z' });
+            }, ['z']);
 
             Assert.Equal('b', res.Single());
             Assert.Equal('b', res.Single());

+ 1 - 1
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Create.cs

@@ -16,7 +16,7 @@ namespace Tests
         [Fact]
         public void Create_Arguments()
         {
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Create<int>(default(Func<IEnumerator<int>>)));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Create<int>(default));
         }
 
         [Fact]

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

@@ -15,10 +15,10 @@ namespace Tests
         public void Distinct_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Distinct<int, int>(null, _ => _));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Distinct<int, int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Distinct<int, int>([1], null));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Distinct<int, int>(null, _ => _, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Distinct<int, int>(new[] { 1 }, null, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Distinct<int, int>(new[] { 1 }, _ => _, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Distinct<int, int>([1], null, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Distinct<int, int>([1], _ => _, null));
         }
 
         [Fact]
@@ -32,7 +32,7 @@ namespace Tests
         public void Distinct2()
         {
             var res = Enumerable.Range(0, 10).Distinct(x => x % 5, new MyEqualityComparer()).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 0, 1 }));
+            Assert.True(Enumerable.SequenceEqual(res, [0, 1]));
         }
 
         private sealed class MyEqualityComparer : IEqualityComparer<int>

+ 6 - 6
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/DistinctUntilChanged.cs

@@ -16,26 +16,26 @@ namespace Tests
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int>(null));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int>(null, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int>([1], null));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int, int>(null, _ => _));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int, int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int, int>([1], null));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int, int>(null, _ => _, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int, int>(new[] { 1 }, null, EqualityComparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int, int>(new[] { 1 }, _ => _, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int, int>([1], null, EqualityComparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.DistinctUntilChanged<int, int>([1], _ => _, null));
         }
 
         [Fact]
         public void DistinctUntilChanged1()
         {
             var res = new[] { 1, 2, 2, 3, 3, 3, 2, 2, 1 }.DistinctUntilChanged().ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 1, 2, 3, 2, 1 }));
+            Assert.True(Enumerable.SequenceEqual(res, [1, 2, 3, 2, 1]));
         }
 
         [Fact]
         public void DistinctUntilChanged2()
         {
             var res = new[] { 1, 1, 2, 3, 4, 5, 5, 6, 7 }.DistinctUntilChanged(x => x / 2).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 1, 2, 4, 6 }));
+            Assert.True(Enumerable.SequenceEqual(res, [1, 2, 4, 6]));
         }
     }
 }

+ 9 - 9
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Do.cs

@@ -17,16 +17,16 @@ namespace Tests
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(null, _ => { }, () => { }));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(null, _ => { }, _ => { }));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(null, _ => { }, _ => { }, () => { }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(new[] { 1 }, default(Action<int>)));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(new[] { 1 }, default(Action<int>), () => { }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(new[] { 1 }, _ => { }, default(Action)));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(new[] { 1 }, default(Action<int>), _ => { }, () => { }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(new[] { 1 }, _ => { }, default(Action<Exception>), () => { }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(new[] { 1 }, _ => { }, _ => { }, default(Action)));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(new[] { 1 }, default(Action<int>), _ => { }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(new[] { 1 }, _ => { }, default(Action<Exception>)));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>([1], default(Action<int>)));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>([1], default, () => { }));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>([1], _ => { }, default(Action)));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>([1], default, _ => { }, () => { }));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>([1], _ => { }, default, () => { }));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>([1], _ => { }, _ => { }, default));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>([1], default, _ => { }));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>([1], _ => { }, default(Action<Exception>)));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(null, new MyObserver()));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>(new[] { 1 }, default(IObserver<int>)));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Do<int>([1], default(IObserver<int>)));
         }
 
         [Fact]

+ 3 - 3
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/DoWhile.cs

@@ -13,7 +13,7 @@ namespace Tests
         [Fact]
         public void DoWhile_Arguments()
         {
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.DoWhile<int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.DoWhile<int>([1], null));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.DoWhile<int>(null, () => true));
         }
 
@@ -22,7 +22,7 @@ namespace Tests
         {
             var x = 5;
             var res = EnumerableEx.DoWhile(EnumerableEx.Defer(() => new[] { x }).Do(_ => x--), () => x > 0).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 5, 4, 3, 2, 1 }));
+            Assert.True(Enumerable.SequenceEqual(res, [5, 4, 3, 2, 1]));
         }
 
         [Fact]
@@ -30,7 +30,7 @@ namespace Tests
         {
             var x = 0;
             var res = EnumerableEx.DoWhile(EnumerableEx.Defer(() => new[] { x }).Do(_ => x--), () => x > 0).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 0 }));
+            Assert.True(Enumerable.SequenceEqual(res, [0]));
         }
     }
 }

+ 3 - 3
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Expand.cs

@@ -13,14 +13,14 @@ namespace Tests
         [Fact]
         public void Expand_Arguments()
         {
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Expand<int>(null, _ => new[] { _ }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Expand<int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Expand<int>(null, _ => [_]));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Expand<int>([1], null));
         }
 
         [Fact]
         public void Expand1()
         {
-            var res = new[] { 0 }.Expand(x => new[] { x + 1 }).Take(10).ToList();
+            var res = new[] { 0 }.Expand(x => [x + 1]).Take(10).ToList();
             Assert.True(Enumerable.SequenceEqual(res, Enumerable.Range(0, 10)));
         }
 

+ 1 - 1
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Finally.cs

@@ -14,7 +14,7 @@ namespace Tests
         public void Finally_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Finally<int>(null, () => { }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Finally<int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Finally<int>([1], null));
         }
 
         [Fact]

+ 3 - 3
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/For.cs

@@ -13,15 +13,15 @@ namespace Tests
         [Fact]
         public void For_Arguments()
         {
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.For<int, int>(null, x => new[] { 1 }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.For<int, int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.For<int, int>(null, x => [1]));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.For<int, int>([1], null));
         }
 
         [Fact]
         public void For1()
         {
             var res = EnumerableEx.For(new[] { 1, 2, 3 }, x => Enumerable.Range(0, x)).ToList();
-            Assert.True(res.SequenceEqual(new[] { 0, 0, 1, 0, 1, 2 }));
+            Assert.True(res.SequenceEqual([0, 0, 1, 0, 1, 2]));
         }
     }
 }

+ 2 - 2
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/ForEach.cs

@@ -14,9 +14,9 @@ namespace Tests
         public void ForEach_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.ForEach<int>(null, x => { }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.ForEach<int>(new[] { 1 }, default(Action<int>)));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.ForEach<int>([1], default(Action<int>)));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.ForEach<int>(null, (x, i) => { }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.ForEach<int>(new[] { 1 }, default(Action<int, int>)));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.ForEach<int>([1], default(Action<int, int>)));
         }
 
         [Fact]

+ 1 - 1
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Generate.cs

@@ -22,7 +22,7 @@ namespace Tests
         public void Generate1()
         {
             var res = EnumerableEx.Generate(0, x => x < 5, x => x + 1, x => x * x).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 0, 1, 4, 9, 16 }));
+            Assert.True(Enumerable.SequenceEqual(res, [0, 1, 4, 9, 16]));
         }
     }
 }

+ 5 - 5
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/If.cs

@@ -13,18 +13,18 @@ namespace Tests
         [Fact]
         public void If_Arguments()
         {
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.If<int>(null, new[] { 1 }));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.If<int>(null, [1]));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.If<int>(() => true, null));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.If<int>(null, new[] { 1 }, new[] { 1 }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.If<int>(() => true, null, new[] { 1 }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.If<int>(() => true, new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.If<int>(null, [1], [1]));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.If<int>(() => true, null, [1]));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.If<int>(() => true, [1], null));
         }
 
         [Fact]
         public void If1()
         {
             var x = 5;
-            var res = EnumerableEx.If(() => x > 0, new[] { +1 }, new[] { -1 });
+            var res = EnumerableEx.If(() => x > 0, [+1], [-1]);
 
             Assert.Equal(+1, res.Single());
 

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

@@ -16,17 +16,17 @@ namespace Tests
         public void MaxBy_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.MaxBy(null, (int x) => x));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.MaxBy(new[] { 1 }, default(Func<int, int>)));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.MaxBy([1], default(Func<int, int>)));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.MaxBy(null, (int x) => x, Comparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.MaxBy(new[] { 1 }, default(Func<int, int>), Comparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.MaxBy(new[] { 1 }, (int x) => x, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.MaxBy([1], default, Comparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.MaxBy([1], (int x) => x, null));
         }
 
         [Fact]
         public void MaxBy1()
         {
             var res = new[] { 2, 5, 0, 7, 4, 3, 6, 2, 1 }.MaxBy(x => x % 3);
-            Assert.True(res.SequenceEqual(new[] { 2, 5, 2 }));
+            Assert.True(res.SequenceEqual([2, 5, 2]));
         }
 
         [Fact]

+ 9 - 9
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Memoize.cs

@@ -22,8 +22,8 @@ namespace Tests
         public void MemoizeLimited_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Memoize<int>(null, 2));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Memoize<int>(new[] { 1 }, 0));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Memoize<int>(new[] { 1 }, -1));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Memoize<int>([1], 0));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Memoize<int>([1], -1));
         }
 
         [Fact]
@@ -227,7 +227,7 @@ namespace Tests
 
             var e1 = ((IEnumerable)rng).GetEnumerator();
             Assert.True(e1.MoveNext());
-            Assert.Equal(0, (int)e1.Current);
+            Assert.Equal(0, (int)e1.Current!);
         }
 
         [Fact]
@@ -251,7 +251,7 @@ namespace Tests
         public void MemoizeLambda_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Memoize<int, int>(null, xs => xs));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Memoize<int, int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Memoize<int, int>([1], null));
         }
 
         [Fact]
@@ -267,9 +267,9 @@ namespace Tests
         public void MemoizeLimitedLambda_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Memoize<int, int>(null, 2, xs => xs));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Memoize<int, int>(new[] { 1 }, 2, null));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Memoize<int, int>(new[] { 1 }, 0, xs => xs));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Memoize<int, int>(new[] { 1 }, -1, xs => xs));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Memoize<int, int>([1], 2, null));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Memoize<int, int>([1], 0, xs => xs));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Memoize<int, int>([1], -1, xs => xs));
         }
 
         [Fact]
@@ -281,12 +281,12 @@ namespace Tests
             Assert.Equal(4, n);
         }
 
-        private static readonly Random s_rand = new Random();
+        private static readonly Random RandSource = new();
 
         private static IEnumerable<int> Rand()
         {
             while (true)
-                yield return s_rand.Next();
+                yield return RandSource.Next();
         }
 
         private sealed class MyException : Exception

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

@@ -16,17 +16,17 @@ namespace Tests
         public void MinBy_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.MinBy(null, (int x) => x));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.MinBy(new[] { 1 }, default(Func<int, int>)));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.MinBy([1], default(Func<int, int>)));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.MinBy(null, (int x) => x, Comparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.MinBy(new[] { 1 }, default(Func<int, int>), Comparer<int>.Default));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.MinBy(new[] { 1 }, (int x) => x, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.MinBy([1], default, Comparer<int>.Default));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.MinBy([1], (int x) => x, null));
         }
 
         [Fact]
         public void MinBy1()
         {
             var res = new[] { 2, 5, 0, 7, 4, 3, 6, 2, 1 }.MinBy(x => x % 3);
-            Assert.True(res.SequenceEqual(new[] { 0, 3, 6 }));
+            Assert.True(res.SequenceEqual([0, 3, 6]));
         }
 
         [Fact]

+ 9 - 9
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/OnErrorResumeNext.cs

@@ -14,9 +14,9 @@ namespace Tests
         [Fact]
         public void OnErrorResumeNext_Arguments()
         {
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.OnErrorResumeNext<int>(null, new[] { 1 }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.OnErrorResumeNext<int>(new[] { 1 }, null));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.OnErrorResumeNext<int>(default(IEnumerable<int>[])));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.OnErrorResumeNext<int>(null, [1]));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.OnErrorResumeNext<int>([1], null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.OnErrorResumeNext<int>(default));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.OnErrorResumeNext<int>(default(IEnumerable<IEnumerable<int>>)));
         }
 
@@ -27,7 +27,7 @@ namespace Tests
             var ys = new[] { 3, 4 };
 
             var res = xs.OnErrorResumeNext(ys);
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 1, 2, 3, 4 }));
+            Assert.True(Enumerable.SequenceEqual(res, [1, 2, 3, 4]));
         }
 
         [Fact]
@@ -37,7 +37,7 @@ namespace Tests
             var ys = new[] { 3, 4 };
 
             var res = xs.OnErrorResumeNext(ys);
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 1, 2, 3, 4 }));
+            Assert.True(Enumerable.SequenceEqual(res, [1, 2, 3, 4]));
         }
 
         [Fact]
@@ -48,7 +48,7 @@ namespace Tests
             var zs = new[] { 5, 6 };
 
             var res = EnumerableEx.OnErrorResumeNext(xs, ys, zs);
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 1, 2, 3, 4, 5, 6 }));
+            Assert.True(Enumerable.SequenceEqual(res, [1, 2, 3, 4, 5, 6]));
         }
 
         [Fact]
@@ -59,7 +59,7 @@ namespace Tests
             var zs = new[] { 5, 6 };
 
             var res = EnumerableEx.OnErrorResumeNext(xs, ys, zs);
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 1, 2, 3, 4, 5, 6 }));
+            Assert.True(Enumerable.SequenceEqual(res, [1, 2, 3, 4, 5, 6]));
         }
 
         [Fact]
@@ -69,7 +69,7 @@ namespace Tests
             var ys = new[] { 3, 4 };
 
             var res = new[] { xs, ys }.OnErrorResumeNext();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 1, 2, 3, 4 }));
+            Assert.True(Enumerable.SequenceEqual(res, [1, 2, 3, 4]));
         }
 
         [Fact]
@@ -79,7 +79,7 @@ namespace Tests
             var ys = new[] { 3, 4 };
 
             var res = new[] { xs, ys }.OnErrorResumeNext();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 1, 2, 3, 4 }));
+            Assert.True(Enumerable.SequenceEqual(res, [1, 2, 3, 4]));
         }
 
         private sealed class MyException : Exception

+ 3 - 3
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Publish.cs

@@ -226,7 +226,7 @@ namespace Tests
         public void PublishLambda_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Publish<int, int>(null, xs => xs));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Publish<int, int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Publish<int, int>([1], null));
         }
 
         [Fact]
@@ -248,12 +248,12 @@ namespace Tests
             }
         }
 
-        private static readonly Random s_rand = new Random();
+        private static readonly Random RandSource = new();
 
         private static IEnumerable<int> Rand()
         {
             while (true)
-                yield return s_rand.Next();
+                yield return RandSource.Next();
         }
     }
 }

+ 1 - 1
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Repeat.cs

@@ -23,7 +23,7 @@ namespace Tests
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Repeat<int>(null));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Repeat<int>(null, 5));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Repeat<int>(new[] { 1 }, -1));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Repeat<int>([1], -1));
         }
 
         [Fact]

+ 1 - 1
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Retry.cs

@@ -15,7 +15,7 @@ namespace Tests
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Retry<int>(null));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Retry<int>(null, 5));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Retry<int>(new[] { 1 }, -1));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.Retry<int>([1], -1));
         }
 
         [Fact]

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

@@ -14,23 +14,23 @@ namespace Tests
         public void Scan_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Scan<int>(null, (x, y) => x + y));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Scan<int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Scan<int>([1], null));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Scan<int, int>(null, 0, (x, y) => x + y));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Scan<int, int>(new[] { 1 }, 0, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Scan<int, int>([1], 0, null));
         }
 
         [Fact]
         public void Scan1()
         {
             var res = Enumerable.Range(0, 5).Scan((n, x) => n + x).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 1, 3, 6, 10 }));
+            Assert.True(Enumerable.SequenceEqual(res, [1, 3, 6, 10]));
         }
 
         [Fact]
         public void Scan2()
         {
             var res = Enumerable.Range(0, 5).Scan(10, (n, x) => n - x).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 10, 9, 7, 4, 0 }));
+            Assert.True(Enumerable.SequenceEqual(res, [10, 9, 7, 4, 0]));
         }
     }
 }

+ 3 - 3
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/SelectMany.cs

@@ -13,15 +13,15 @@ namespace Tests
         [Fact]
         public void SelectMany_Arguments()
         {
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.SelectMany<int, int>(null, new[] { 1 }));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.SelectMany<int, int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.SelectMany<int, int>(null, [1]));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.SelectMany<int, int>([1], null));
         }
 
         [Fact]
         public void SelectMany1()
         {
             var res = new[] { 1, 2 }.SelectMany(new[] { 'a', 'b', 'c' }).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 'a', 'b', 'c', 'a', 'b', 'c' }));
+            Assert.True(Enumerable.SequenceEqual(res, ['a', 'b', 'c', 'a', 'b', 'c']));
         }
     }
 }

+ 3 - 3
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Share.cs

@@ -64,7 +64,7 @@ namespace Tests
             NoNext(e1);
         }
 
-        //[Fact]
+        [Fact]
         public void Share4()
         {
             var rng = Enumerable.Range(0, 5).Share();
@@ -108,7 +108,7 @@ namespace Tests
         public void ShareLambda_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Share<int, int>(null, xs => xs));
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Share<int, int>(new[] { 1 }, null));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Share<int, int>([1], null));
         }
 
         [Fact]
@@ -116,7 +116,7 @@ namespace Tests
         {
             var n = 0;
             var res = Enumerable.Range(0, 10).Do(_ => n++).Share(xs => xs.Zip(xs, (l, r) => l + r).Take(4)).ToList();
-            Assert.True(res.SequenceEqual(new[] { 0 + 1, 2 + 3, 4 + 5, 6 + 7 }));
+            Assert.True(res.SequenceEqual([0 + 1, 2 + 3, 4 + 5, 6 + 7]));
             Assert.Equal(8, n);
         }
     }

+ 1 - 1
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/SkipLast.cs

@@ -15,7 +15,7 @@ namespace Tests
         public void SkipLast_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.SkipLast<int>(null, 5));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.SkipLast<int>(new[] { 1 }, -1));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.SkipLast<int>([1], -1));
         }
 
         [Fact]

+ 2 - 2
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/TakeLast.cs

@@ -15,7 +15,7 @@ namespace Tests
         public void TakeLast_Arguments()
         {
             AssertThrows<ArgumentNullException>(() => EnumerableEx.TakeLast<int>(null, 5));
-            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.TakeLast<int>(new[] { 1 }, -1));
+            AssertThrows<ArgumentOutOfRangeException>(() => EnumerableEx.TakeLast<int>([1], -1));
         }
 
         [Fact]
@@ -23,7 +23,7 @@ namespace Tests
         {
             var e = Enumerable.Range(1, 5);
             var r = e.TakeLast(0).ToList();
-            Assert.True(Enumerable.SequenceEqual(r, Enumerable.Empty<int>()));
+            Assert.True(Enumerable.SequenceEqual(r, []));
         }
 
         [Fact]

+ 1 - 1
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/Using.cs

@@ -13,7 +13,7 @@ namespace Tests
         [Fact]
         public void Using_Arguments()
         {
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.Using<int, MyDisposable>(null, d => new[] { 1 }));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.Using<int, MyDisposable>(null, d => [1]));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.Using<int, MyDisposable>(() => new MyDisposable(), null));
         }
 

+ 3 - 3
Ix.NET/Source/System.Interactive.Tests/System/Linq/Operators/While.cs

@@ -13,7 +13,7 @@ namespace Tests
         [Fact]
         public void While_Arguments()
         {
-            AssertThrows<ArgumentNullException>(() => EnumerableEx.While<int>(null, new[] { 1 }));
+            AssertThrows<ArgumentNullException>(() => EnumerableEx.While<int>(null, [1]));
             AssertThrows<ArgumentNullException>(() => EnumerableEx.While<int>(() => true, null));
         }
 
@@ -22,7 +22,7 @@ namespace Tests
         {
             var x = 5;
             var res = EnumerableEx.While(() => x > 0, EnumerableEx.Defer(() => new[] { x }).Do(_ => x--)).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new[] { 5, 4, 3, 2, 1 }));
+            Assert.True(Enumerable.SequenceEqual(res, [5, 4, 3, 2, 1]));
         }
 
         [Fact]
@@ -30,7 +30,7 @@ namespace Tests
         {
             var x = 0;
             var res = EnumerableEx.While(() => x > 0, EnumerableEx.Defer(() => new[] { x }).Do(_ => x--)).ToList();
-            Assert.True(Enumerable.SequenceEqual(res, new int[0]));
+            Assert.True(Enumerable.SequenceEqual(res, []));
         }
     }
 }

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

@@ -10,7 +10,6 @@ namespace Tests
 {
     public partial class Tests
     {
-#pragma warning disable xUnit1013 // Public method should be marked as test
         public void AssertThrows<E>(Action a)
             where E : Exception
         {
@@ -41,6 +40,5 @@ namespace Tests
             Assert.True(e.MoveNext());
             Assert.Equal(value, e.Current);
         }
-#pragma warning restore xUnit1013 // Public method should be marked as test
     }
 }

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

@@ -1,4 +1,4 @@
-<Project Sdk="MSBuild.Sdk.Extras">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <Description>Interactive Extensions Main Library used to express queries over enumerable sequences.</Description>
@@ -10,7 +10,32 @@
 
   <ItemGroup>
     <EmbeddedResource Include="Properties\System.Interactive.rd.xml" />
-    <ReferenceAssemblyProjectReference Include="..\refs\System.Interactive.Ref\System.Interactive.csproj" ReferenceOutputAssembly="false" />
   </ItemGroup>
+
+  <!--
+  Incorporate the reference assemblies. Note that these have a different set of TFMs from the proper assemblies.
+  
+  See ../../Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md
+  -->
+  <ItemGroup>
+    <None Include="../refs/System.Interactive/bin/$(Configuration)/$(TargetFramework)/**"
+          PackagePath="ref/$(TargetFramework)"
+          Pack="true" />
+  </ItemGroup>
+
+  <!--
+  These warnings occur because we are deliberately creating a lib/ref mismatch. There doesn't seem to be
+  an official way to do that, so we have to suppress the warnings.
   
+  See ../../Documentation/adr/0001-Ix-Ref-Assembly-Mismatches.md for an explanation of this bizarreness.
+  -->
+
+  <PropertyGroup>
+    <!--
+    NU5128: lib/ref mismatch. This is deliberate, as explained in the ADR.
+    NU5131: spurious missing file errors. It appears that the build is confused by what we're doing.
+    -->
+    <NoWarn>$(NoWarn);NU5128;NU5131</NoWarn>
+  </PropertyGroup>
+
 </Project>

+ 1 - 1
Ix.NET/Source/System.Interactive/System/Linq/MaxRefCountList.cs

@@ -9,7 +9,7 @@ namespace System.Linq
 {
     internal sealed class MaxRefCountList<T> : IRefCountList<T>
     {
-        private readonly IList<T> _list = new List<T>();
+        private readonly IList<T> _list = [];
 
         public void Clear() => _list.Clear();
 

+ 1 - 1
Ix.NET/Source/System.Interactive/System/Linq/Operators/Case.cs

@@ -23,7 +23,7 @@ namespace System.Linq
             if (sources == null)
                 throw new ArgumentNullException(nameof(sources));
 
-            return Case(selector, sources, Enumerable.Empty<TResult>());
+            return Case(selector, sources, []);
         }
 
         /// <summary>

+ 2 - 6
Ix.NET/Source/System.Interactive/System/Linq/Operators/Create.cs

@@ -43,13 +43,9 @@ namespace System.Linq
             }
         }
 
-        private sealed class AnonymousEnumerable<TResult> : IEnumerable<TResult>
+        private sealed class AnonymousEnumerable<TResult>(Func<IEnumerator<TResult>> getEnumerator) : IEnumerable<TResult>
         {
-            private readonly Func<IEnumerator<TResult>> _getEnumerator;
-
-            public AnonymousEnumerable(Func<IEnumerator<TResult>> getEnumerator) => _getEnumerator = getEnumerator;
-
-            public IEnumerator<TResult> GetEnumerator() => _getEnumerator();
+            public IEnumerator<TResult> GetEnumerator() => getEnumerator();
 
             IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
         }

+ 1 - 1
Ix.NET/Source/System.Interactive/System/Linq/Operators/If.cs

@@ -43,7 +43,7 @@ namespace System.Linq
             if (thenSource == null)
                 throw new ArgumentNullException(nameof(thenSource));
 
-            return Defer(() => condition() ? thenSource : Enumerable.Empty<TResult>());
+            return Defer(() => condition() ? thenSource : []);
         }
     }
 }

+ 1 - 1
Ix.NET/Source/System.Interactive/System/Linq/Operators/MaxByWithTies.cs

@@ -72,7 +72,7 @@ namespace System.Linq
                     }
                     else if (cmp > 0)
                     {
-                        result = new List<TSource> { cur };
+                        result = [cur];
                         resKey = key;
                     }
                 }

+ 2 - 3
Ix.NET/Source/System.Interactive/System/Linq/Operators/Memoize.cs

@@ -113,7 +113,7 @@ namespace System.Linq
 
         private sealed class MemoizedBuffer<T> : IBuffer<T>
         {
-            private readonly object _gate = new object();
+            private readonly object _gate = new();
             private readonly IRefCountList<T> _buffer;
             private readonly IEnumerator<T> _source;
 
@@ -231,8 +231,7 @@ namespace System.Linq
                 }
                 finally
                 {
-                    if (_buffer != null)
-                        _buffer.Done(i + 1);
+                    _buffer?.Done(i + 1);
                 }
             }
         }

+ 1 - 1
Ix.NET/Source/System.Interactive/System/Linq/Operators/Publish.cs

@@ -61,7 +61,7 @@ namespace System.Linq
 
         private sealed class PublishedBuffer<T> : IBuffer<T>
         {
-            private readonly object _gate = new object();
+            private readonly object _gate = new();
             private readonly RefCountList<T> _buffer;
             private readonly IEnumerator<T> _source;
 

+ 2 - 7
Ix.NET/Source/System.Interactive/System/Linq/Operators/Share.cs

@@ -56,16 +56,11 @@ namespace System.Linq
             return Create(() => selector(source.Share()).GetEnumerator());
         }
 
-        private class SharedBuffer<T> : IBuffer<T>
+        private class SharedBuffer<T>(IEnumerator<T> source) : IBuffer<T>
         {
-            private readonly IEnumerator<T> _source;
+            private readonly IEnumerator<T> _source = source;
             private bool _disposed;
 
-            public SharedBuffer(IEnumerator<T> source)
-            {
-                _source = source;
-            }
-
             public IEnumerator<T> GetEnumerator()
             {
                 if (_disposed)

+ 1 - 1
Ix.NET/Source/System.Interactive/System/Linq/Operators/SkipLast.cs

@@ -28,7 +28,6 @@ namespace System.Linq
 
             return SkipLastCore(source, count);
         }
-#endif
 
         private static IEnumerable<TSource> SkipLastCore<TSource>(this IEnumerable<TSource> source, int count)
         {
@@ -44,5 +43,6 @@ namespace System.Linq
                 }
             }
         }
+#endif
     }
 }

+ 1 - 1
Ix.NET/Source/System.Interactive/System/Linq/Operators/TakeLast.cs

@@ -25,7 +25,6 @@ namespace System.Linq
 
             return TakeLastCore(source, count);
         }
-#endif
 
         private static IEnumerable<TSource> TakeLastCore<TSource>(IEnumerable<TSource> source, int count)
         {
@@ -51,5 +50,6 @@ namespace System.Linq
                 yield return q.Dequeue();
             }
         }
+#endif
     }
 }

+ 2 - 2
Ix.NET/Source/System.Interactive/System/Linq/Operators/Throw.cs

@@ -25,9 +25,9 @@ namespace System.Linq
         private static IEnumerable<TResult> ThrowCore<TResult>(Exception exception)
         {
             throw exception;
-#pragma warning disable 0162
+#pragma warning disable CS0162 // Unreachable code detected
             yield break;
-#pragma warning restore 0162
+#pragma warning restore CS0162 // Unreachable code detected
         }
     }
 }

+ 3 - 9
Ix.NET/Source/System.Interactive/System/Linq/RefCountList.cs

@@ -7,17 +7,11 @@ using System.Diagnostics;
 
 namespace System.Linq
 {
-    internal sealed class RefCountList<T> : IRefCountList<T>
+    internal sealed class RefCountList<T>(int readerCount) : IRefCountList<T>
     {
-        private readonly IDictionary<int, RefCount> _list;
+        private readonly IDictionary<int, RefCount> _list = new Dictionary<int, RefCount>();
 
-        public RefCountList(int readerCount)
-        {
-            ReaderCount = readerCount;
-            _list = new Dictionary<int, RefCount>();
-        }
-
-        public int ReaderCount { get; set; }
+        public int ReaderCount { get; set; } = readerCount;
 
         public void Clear() => _list.Clear();
 

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

@@ -1,7 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net6.0;netcoreapp3.1</TargetFrameworks>
+    <!-- See NetCore31TestReadme.txt for why we still use netcoreapp3.1 -->
+    <TargetFrameworks>net48;net8.0;net6.0;netcoreapp3.1</TargetFrameworks>
     <NoWarn>$(NoWarn);CS0618</NoWarn>
   </PropertyGroup>
 

+ 5 - 0
Ix.NET/Source/System.Linq.Async.Queryable/System.Linq.Async.Queryable.csproj

@@ -25,4 +25,9 @@
       <Generator>TextTemplatingFileGenerator</Generator>
     </None>
   </ItemGroup>
+
+  <ItemGroup>
+    <!-- T4. -->
+    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
+  </ItemGroup>
 </Project>

+ 1 - 1
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableQuery.cs

@@ -135,7 +135,7 @@ namespace System.Linq
         /// <returns>String representation of the enumerable sequence.</returns>
         public override string? ToString()
         {
-            if (!(_expression is ConstantExpression ce) || ce.Value != this)
+            if (_expression is not ConstantExpression ce || ce.Value != this)
             {
                 return _expression.ToString();
             }

+ 3 - 6
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableRewriter.cs

@@ -23,7 +23,7 @@ namespace System.Linq
             // Not an expression representation obtained from the async enumerable query provider,
             // so just a plain constant that can be returned as-is.
             //
-            if (!(node.Value is AsyncEnumerableQuery enumerableQuery))
+            if (node.Value is not AsyncEnumerableQuery enumerableQuery)
             {
                 return node;
             }
@@ -46,7 +46,7 @@ namespace System.Linq
 
         protected override Expression VisitMethodCall(MethodCallExpression node)
         {
-            var obj = Visit(node.Object);
+            var obj = Visit(node.Object)!;
             var args = Visit(node.Arguments);
 
             //
@@ -396,10 +396,7 @@ namespace System.Linq
             //
             // Ensure the cached lookup table for AsyncEnumerable methods is initialized.
             //
-            if (_methods == null)
-            {
-                _methods = typeof(AsyncEnumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).ToLookup(m => m.Name);
-            }
+            _methods ??= typeof(AsyncEnumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).ToLookup(m => m.Name);
 
             //
             // Find a match based on the method name and the argument types.

Разница между файлами не показана из-за своего большого размера
+ 112 - 112
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncQueryable.Generated.cs


+ 3 - 3
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncQueryable.Generated.tt

@@ -3,9 +3,9 @@
 // See the LICENSE file in the project root for more information. 
 
 <#@ template debug="false" hostspecific="false" language="C#" #>
-<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net461\Microsoft.Bcl.AsyncInterfaces.dll" #>
-<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net461\System.Threading.Tasks.Extensions.dll" #>
-<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net461\System.Linq.Async.dll" #>
+<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net48\Microsoft.Bcl.AsyncInterfaces.dll" #>
+<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net48\System.Threading.Tasks.Extensions.dll" #>
+<#@ assembly name="$(ProjectDir)\..\System.Linq.Async\bin\$(Configuration)\net48\System.Linq.Async.dll" #>
 <#@ output extension=".cs" #>
 <#
 var asyncEnumerableType = typeof(AsyncEnumerable);

+ 0 - 16
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncQueryable.cs

@@ -34,22 +34,6 @@ namespace System.Linq
             return new AsyncEnumerableQuery<TElement>(source);
         }
 
-        private static MethodInfo? s_Zip__TFirst_TSecond__2__0;
-        
-        private static MethodInfo Zip__TFirst_TSecond__2__0(Type TFirst, Type TSecond) =>
-            (s_Zip__TFirst_TSecond__2__0 ??
-            (s_Zip__TFirst_TSecond__2__0 = new Func<IAsyncQueryable<object>, IAsyncEnumerable<object>, IAsyncQueryable<ValueTuple<object, object>>>(Zip<object, object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TFirst, TSecond);
-
-        public static IAsyncQueryable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>(this IAsyncQueryable<TFirst> first, IAsyncEnumerable<TSecond> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return first.Provider.CreateQuery<(TFirst, TSecond)>(Expression.Call(Zip__TFirst_TSecond__2__0(typeof(TFirst), typeof(TSecond)), first.Expression, GetSourceExpression(second)));
-        }
-
         private static Expression GetSourceExpression<TSource>(IAsyncEnumerable<TSource> source)
         {
             if (source is IAsyncQueryable<TSource> queryable)

+ 9 - 2
Ix.NET/Source/System.Linq.Async.Tests/System.Linq.Async.Tests.csproj

@@ -1,8 +1,15 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net48;net6.0;netcoreapp3.1</TargetFrameworks>
-    <NoWarn>$(NoWarn);CS0618;CS8603;CS8625</NoWarn>
+    <!-- See NetCore31TestReadme.txt for why we still use netcoreapp3.1 -->
+    <TargetFrameworks>net48;net8.0;net6.0;netcoreapp3.1</TargetFrameworks>
+
+    <!--
+    CA1510: Use ArgumentNullException.ThrowIfNull - not available on .NET 4.8
+    CA1861: Extract constant arrays to 'static readonly' fields. With these tests we generally prioritize readability over performance.
+    -->
+
+    <NoWarn>$(NoWarn);CS0618;CS8603;CS8625;CA1510;CA1822;CA1861</NoWarn>
   </PropertyGroup>
 
   <ItemGroup>

+ 9 - 9
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Aggregate.cs

@@ -47,7 +47,7 @@ namespace Tests
         [Fact]
         public async Task AggregateAsync_Empty()
         {
-            var xs = new int[0].ToAsyncEnumerable();
+            var xs = Array.Empty<int>().ToAsyncEnumerable();
             var ys = xs.AggregateAsync((x, y) => x * y);
             await AssertThrowsAsync<InvalidOperationException>(ys.AsTask());
         }
@@ -81,7 +81,7 @@ namespace Tests
         [Fact]
         public async Task AggregateAsync_Seed_Emtpy()
         {
-            var xs = new int[0].ToAsyncEnumerable();
+            var xs = Array.Empty<int>().ToAsyncEnumerable();
             var ys = xs.AggregateAsync(1, (x, y) => x * y);
             Assert.Equal(1, await ys);
         }
@@ -115,7 +115,7 @@ namespace Tests
         [Fact]
         public async Task AggregateAsync_Seed_Result_Empty()
         {
-            var xs = new int[0].ToAsyncEnumerable();
+            var xs = Array.Empty<int>().ToAsyncEnumerable();
             var ys = xs.AggregateAsync(1, (x, y) => x * y, x => x + 1);
             Assert.Equal(2, await ys);
         }
@@ -182,7 +182,7 @@ namespace Tests
         [Fact]
         public async Task AggregateAwaitAsync_Empty()
         {
-            var xs = new int[0].ToAsyncEnumerable();
+            var xs = Array.Empty<int>().ToAsyncEnumerable();
             var ys = xs.AggregateAwaitAsync((x, y) => new ValueTask<int>(x * y));
             await AssertThrowsAsync<InvalidOperationException>(ys.AsTask());
         }
@@ -216,7 +216,7 @@ namespace Tests
         [Fact]
         public async Task AggregateAwaitAsync_Seed_Emtpy()
         {
-            var xs = new int[0].ToAsyncEnumerable();
+            var xs = Array.Empty<int>().ToAsyncEnumerable();
             var ys = xs.AggregateAwaitAsync(1, (x, y) => new ValueTask<int>(x * y));
             Assert.Equal(1, await ys);
         }
@@ -250,7 +250,7 @@ namespace Tests
         [Fact]
         public async Task AggregateAwaitAsync_Seed_Result_Empty()
         {
-            var xs = new int[0].ToAsyncEnumerable();
+            var xs = Array.Empty<int>().ToAsyncEnumerable();
             var ys = xs.AggregateAwaitAsync(1, (x, y) => new ValueTask<int>(x * y), x => new ValueTask<int>(x + 1));
             Assert.Equal(2, await ys);
         }
@@ -318,7 +318,7 @@ namespace Tests
         [Fact]
         public async Task AggregateAwaitWithCancellationAsync_Empty()
         {
-            var xs = new int[0].ToAsyncEnumerable();
+            var xs = Array.Empty<int>().ToAsyncEnumerable();
             var ys = xs.AggregateAwaitWithCancellationAsync((x, y, ct) => new ValueTask<int>(x * y));
             await AssertThrowsAsync<InvalidOperationException>(ys.AsTask());
         }
@@ -352,7 +352,7 @@ namespace Tests
         [Fact]
         public async Task AggregateAwaitWithCancellationAsync_Seed_Emtpy()
         {
-            var xs = new int[0].ToAsyncEnumerable();
+            var xs = Array.Empty<int>().ToAsyncEnumerable();
             var ys = xs.AggregateAwaitWithCancellationAsync(1, (x, y, ct) => new ValueTask<int>(x * y));
             Assert.Equal(1, await ys);
         }
@@ -386,7 +386,7 @@ namespace Tests
         [Fact]
         public async Task AggregateAwaitWithCancellationAsync_Seed_Result_Empty()
         {
-            var xs = new int[0].ToAsyncEnumerable();
+            var xs = Array.Empty<int>().ToAsyncEnumerable();
             var ys = xs.AggregateAwaitWithCancellationAsync(1, (x, y, ct) => new ValueTask<int>(x * y), (x, ct) => new ValueTask<int>(x + 1));
             Assert.Equal(2, await ys);
         }

+ 1 - 1
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Any.cs

@@ -65,7 +65,7 @@ namespace Tests
         [Fact]
         public async Task AnyAsync_NoSelector_Empty()
         {
-            var res = new int[0].ToAsyncEnumerable().AnyAsync();
+            var res = Array.Empty<int>().ToAsyncEnumerable().AnyAsync();
             Assert.False(await res);
         }
 

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

@@ -22,7 +22,7 @@ namespace Tests
         [Fact]
         public async Task CountAsync_Simple()
         {
-            Assert.Equal(0, await new int[0].ToAsyncEnumerable().CountAsync());
+            Assert.Equal(0, await Array.Empty<int>().ToAsyncEnumerable().CountAsync());
             Assert.Equal(3, await new[] { 1, 2, 3 }.ToAsyncEnumerable().CountAsync());
         }
 
@@ -46,7 +46,7 @@ namespace Tests
         [Fact]
         public async Task CountAsync_Predicate()
         {
-            Assert.Equal(0, await new int[0].ToAsyncEnumerable().CountAsync(x => x < 3));
+            Assert.Equal(0, await Array.Empty<int>().ToAsyncEnumerable().CountAsync(x => x < 3));
             Assert.Equal(2, await new[] { 1, 2, 3 }.ToAsyncEnumerable().CountAsync(x => x < 3));
         }
 
@@ -78,7 +78,7 @@ namespace Tests
         [Fact]
         public async Task CountAwaitAsync()
         {
-            Assert.Equal(0, await new int[0].ToAsyncEnumerable().CountAwaitAsync(x => new ValueTask<bool>(x < 3)));
+            Assert.Equal(0, await Array.Empty<int>().ToAsyncEnumerable().CountAwaitAsync(x => new ValueTask<bool>(x < 3)));
             Assert.Equal(2, await new[] { 1, 2, 3 }.ToAsyncEnumerable().CountAwaitAsync(x => new ValueTask<bool>(x < 3)));
         }
 
@@ -111,7 +111,7 @@ namespace Tests
         [Fact]
         public async Task CountAwaitWithCancellationAsync()
         {
-            Assert.Equal(0, await new int[0].ToAsyncEnumerable().CountAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x < 3)));
+            Assert.Equal(0, await Array.Empty<int>().ToAsyncEnumerable().CountAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x < 3)));
             Assert.Equal(2, await new[] { 1, 2, 3 }.ToAsyncEnumerable().CountAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x < 3)));
         }
 

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

@@ -29,14 +29,14 @@ namespace Tests
         [Fact]
         public async Task FirstAsync_NoParam_Empty_Enumerable()
         {
-            var res = new int[0].Select(x => x).ToAsyncEnumerable().FirstAsync();
+            var res = Array.Empty<int>().Select(x => x).ToAsyncEnumerable().FirstAsync();
             await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
         }
 
         [Fact]
         public async Task FirstAsync_NoParam_Empty_IList()
         {
-            var res = new int[0].ToAsyncEnumerable().FirstAsync();
+            var res = Array.Empty<int>().ToAsyncEnumerable().FirstAsync();
             await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
         }
 

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

@@ -29,14 +29,14 @@ namespace Tests
         [Fact]
         public async Task FirstOrDefaultAsync_NoParam_Empty_Enumerable()
         {
-            var res = new int[0].Select(x => x).ToAsyncEnumerable().FirstOrDefaultAsync();
+            var res = Array.Empty<int>().Select(x => x).ToAsyncEnumerable().FirstOrDefaultAsync();
             Assert.Equal(0, await res);
         }
 
         [Fact]
         public async Task FirstOrDefaultAsync_NoParam_Empty_IList()
         {
-            var res = new int[0].ToAsyncEnumerable().FirstOrDefaultAsync();
+            var res = Array.Empty<int>().ToAsyncEnumerable().FirstOrDefaultAsync();
             Assert.Equal(0, await res);
         }
 

+ 5 - 1
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/GroupBy.cs

@@ -2,6 +2,10 @@
 // The .NET Foundation licenses this file to you under the MIT License.
 // See the LICENSE file in the project root for more information. 
 
+#if NET6_0_OR_GREATER
+#pragma warning disable CA2012 // Use ValueTasks correctly. These tests need to use Result to verify correct operation, so we can't avoid breaking this rule.
+#endif
+
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -826,7 +830,7 @@ namespace Tests
             public string Key { get; }
             public int Item { get; }
 
-            public bool Equals(Kvp other)
+            public bool Equals(Kvp? other)
             {
                 if (other is null) return false;
                 if (ReferenceEquals(this, other)) return true;

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

@@ -2,6 +2,10 @@
 // The .NET Foundation licenses this file to you under the MIT License.
 // See the LICENSE file in the project root for more information. 
 
+#if NET6_0_OR_GREATER
+#pragma warning disable CA2012 // Use ValueTasks correctly. These tests need to use Result to verify correct operation, so we can't avoid breaking this rule.
+#endif
+
 using System;
 using System.Collections.Generic;
 using System.Linq;

+ 19 - 19
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Join.cs

@@ -167,19 +167,19 @@ namespace Tests
         {
             var customers = new List<Customer>
             {
-                new Customer { CustomerId = "ALFKI" },
-                new Customer { CustomerId = "ANANT" },
-                new Customer { CustomerId = "FISSA" },
+                new() { CustomerId = "ALFKI" },
+                new() { CustomerId = "ANANT" },
+                new() { CustomerId = "FISSA" },
             };
 
             var orders = new List<Order>
             {
-                new Order { OrderId = 1, CustomerId = "ALFKI"},
-                new Order { OrderId = 2, CustomerId = "ALFKI"},
-                new Order { OrderId = 3, CustomerId = "ALFKI"},
-                new Order { OrderId = 4, CustomerId = "FISSA"},
-                new Order { OrderId = 5, CustomerId = "FISSA"},
-                new Order { OrderId = 6, CustomerId = "FISSA"},
+                new() { OrderId = 1, CustomerId = "ALFKI"},
+                new() { OrderId = 2, CustomerId = "ALFKI"},
+                new() { OrderId = 3, CustomerId = "ALFKI"},
+                new() { OrderId = 4, CustomerId = "FISSA"},
+                new() { OrderId = 5, CustomerId = "FISSA"},
+                new() { OrderId = 6, CustomerId = "FISSA"},
             };
 
             var asyncResult = customers.ToAsyncEnumerable()
@@ -201,18 +201,18 @@ namespace Tests
         {
             var customers = new List<Customer>
             {
-                new Customer {CustomerId = "ANANT"},
-                new Customer {CustomerId = "ALFKI"},
-                new Customer {CustomerId = "FISSA"}
+                new() {CustomerId = "ANANT"},
+                new() {CustomerId = "ALFKI"},
+                new() {CustomerId = "FISSA"}
             };
             var orders = new List<Order>
             {
-                new Order { OrderId = 1, CustomerId = "ALFKI"},
-                new Order { OrderId = 2, CustomerId = "ALFKI"},
-                new Order { OrderId = 3, CustomerId = "ALFKI"},
-                new Order { OrderId = 4, CustomerId = "FISSA"},
-                new Order { OrderId = 5, CustomerId = "FISSA"},
-                new Order { OrderId = 6, CustomerId = "FISSA"},
+                new() { OrderId = 1, CustomerId = "ALFKI"},
+                new() { OrderId = 2, CustomerId = "ALFKI"},
+                new() { OrderId = 3, CustomerId = "ALFKI"},
+                new() { OrderId = 4, CustomerId = "FISSA"},
+                new() { OrderId = 5, CustomerId = "FISSA"},
+                new() { OrderId = 6, CustomerId = "FISSA"},
             };
 
             var asyncResult = customers.ToAsyncEnumerable()
@@ -245,7 +245,7 @@ namespace Tests
             public int OrderId { get; set; }
             public string? CustomerId { get; set; }
 
-            public bool Equals(CustomerOrder other)
+            public bool Equals(CustomerOrder? other)
             {
                 if (other is null) return false;
                 if (ReferenceEquals(this, other)) return true;

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

@@ -29,14 +29,14 @@ namespace Tests
         [Fact]
         public async Task LastAsync_NoParam_Empty_Enumerable()
         {
-            var res = new int[0].Select(x => x).ToAsyncEnumerable().LastAsync();
+            var res = Array.Empty<int>().Select(x => x).ToAsyncEnumerable().LastAsync();
             await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
         }
 
         [Fact]
         public async Task LastAsync_NoParam_Empty_IList()
         {
-            var res = new int[0].ToAsyncEnumerable().LastAsync();
+            var res = Array.Empty<int>().ToAsyncEnumerable().LastAsync();
             await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
         }
 

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

@@ -29,14 +29,14 @@ namespace Tests
         [Fact]
         public async Task LasyOrDefaultAsync_NoParam_Empty_Enumerable()
         {
-            var res = new int[0].Select(x => x).ToAsyncEnumerable().LastOrDefaultAsync();
+            var res = Array.Empty<int>().Select(x => x).ToAsyncEnumerable().LastOrDefaultAsync();
             Assert.Equal(0, await res);
         }
 
         [Fact]
         public async Task LastOrDefaultAsync_NoParam_Empty_IList()
         {
-            var res = new int[0].ToAsyncEnumerable().LastOrDefaultAsync();
+            var res = Array.Empty<int>().ToAsyncEnumerable().LastOrDefaultAsync();
             Assert.Equal(0, await res);
         }
 

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

@@ -22,7 +22,7 @@ namespace Tests
         [Fact]
         public async Task LongCountAsync_Simple()
         {
-            Assert.Equal(0, await new int[0].ToAsyncEnumerable().LongCountAsync());
+            Assert.Equal(0, await Array.Empty<int>().ToAsyncEnumerable().LongCountAsync());
             Assert.Equal(3, await new[] { 1, 2, 3 }.ToAsyncEnumerable().LongCountAsync());
         }
 
@@ -46,7 +46,7 @@ namespace Tests
         [Fact]
         public async Task LongCountAsync_Predicate_Simple()
         {
-            Assert.Equal(0, await new int[0].ToAsyncEnumerable().LongCountAsync(x => x < 3));
+            Assert.Equal(0, await Array.Empty<int>().ToAsyncEnumerable().LongCountAsync(x => x < 3));
             Assert.Equal(2, await new[] { 1, 2, 3 }.ToAsyncEnumerable().LongCountAsync(x => x < 3));
         }
 
@@ -78,7 +78,7 @@ namespace Tests
         [Fact]
         public async Task LongCountAwaitAsync_Predicate()
         {
-            Assert.Equal(0, await new int[0].ToAsyncEnumerable().LongCountAwaitAsync(x => new ValueTask<bool>(x < 3)));
+            Assert.Equal(0, await Array.Empty<int>().ToAsyncEnumerable().LongCountAwaitAsync(x => new ValueTask<bool>(x < 3)));
             Assert.Equal(2, await new[] { 1, 2, 3 }.ToAsyncEnumerable().LongCountAwaitAsync(x => new ValueTask<bool>(x < 3)));
         }
 
@@ -111,7 +111,7 @@ namespace Tests
         [Fact]
         public async Task LongCountAwaitWithCancellationAsync_Predicate()
         {
-            Assert.Equal(0, await new int[0].ToAsyncEnumerable().LongCountAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x < 3)));
+            Assert.Equal(0, await Array.Empty<int>().ToAsyncEnumerable().LongCountAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x < 3)));
             Assert.Equal(2, await new[] { 1, 2, 3 }.ToAsyncEnumerable().LongCountAwaitWithCancellationAsync((x, ct) => new ValueTask<bool>(x < 3)));
         }
 

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

@@ -359,7 +359,7 @@ namespace Tests
         [Fact]
         public async Task MaxAsync_TSource_Value_Empty()
         {
-            var xs = new DateTimeOffset[0].ToAsyncEnumerable();
+            var xs = Array.Empty<DateTimeOffset>().ToAsyncEnumerable();
             await AssertThrowsAsync<InvalidOperationException>(xs.MaxAsync().AsTask());
             await AssertThrowsAsync<InvalidOperationException>(xs.MaxAsync(x => x).AsTask());
             await AssertThrowsAsync<InvalidOperationException>(xs.MaxAwaitAsync(x => new ValueTask<DateTimeOffset>(x)).AsTask());
@@ -371,7 +371,7 @@ namespace Tests
         [Fact]
         public async Task MaxAsync_TSource_NonValue_Empty()
         {
-            var xs = new string[0].ToAsyncEnumerable();
+            var xs = Array.Empty<string>().ToAsyncEnumerable();
             Assert.Null(await xs.MaxAsync());
             Assert.Null(await xs.MaxAsync(x => x));
             Assert.Null(await xs.MaxAwaitAsync(x => new ValueTask<string>(x)));
@@ -383,7 +383,7 @@ namespace Tests
         [Fact]
         public async Task MaxAsync_TSource_NullableValue_Empty()
         {
-            var xs = new DateTimeOffset?[0].ToAsyncEnumerable();
+            var xs = Array.Empty<DateTimeOffset?>().ToAsyncEnumerable();
             Assert.Null(await xs.MaxAsync());
             Assert.Null(await xs.MaxAsync(x => x));
             Assert.Null(await xs.MaxAwaitAsync(x => new ValueTask<DateTimeOffset?>(x)));

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

@@ -359,7 +359,7 @@ namespace Tests
         [Fact]
         public async Task MinAsync_TSource_Value_Empty()
         {
-            var xs = new DateTimeOffset[0].ToAsyncEnumerable();
+            var xs = Array.Empty<DateTimeOffset>().ToAsyncEnumerable();
             await AssertThrowsAsync<InvalidOperationException>(xs.MinAsync().AsTask());
             await AssertThrowsAsync<InvalidOperationException>(xs.MinAsync(x => x).AsTask());
             await AssertThrowsAsync<InvalidOperationException>(xs.MinAwaitAsync(x => new ValueTask<DateTimeOffset>(x)).AsTask());
@@ -371,7 +371,7 @@ namespace Tests
         [Fact]
         public async Task MinAsync_TSource_NonValue_Empty()
         {
-            var xs = new string[0].ToAsyncEnumerable();
+            var xs = Array.Empty<string>().ToAsyncEnumerable();
             Assert.Null(await xs.MinAsync());
             Assert.Null(await xs.MinAsync(x => x));
             Assert.Null(await xs.MinAwaitAsync(x => new ValueTask<string>(x)));
@@ -383,7 +383,7 @@ namespace Tests
         [Fact]
         public async Task MinAsync_TSource_NullableValue_Empty()
         {
-            var xs = new DateTimeOffset?[0].ToAsyncEnumerable();
+            var xs = Array.Empty<DateTimeOffset?>().ToAsyncEnumerable();
             Assert.Null(await xs.MinAsync());
             Assert.Null(await xs.MinAsync(x => x));
             Assert.Null(await xs.MinAwaitAsync(x => new ValueTask<DateTimeOffset?>(x)));

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

@@ -63,7 +63,7 @@ namespace Tests
             Assert.Equal(2, await xs.Take(1024).FirstAsync());
             Assert.Equal(6, await xs.Take(1024).LastAsync());
 
-            Assert.Equal(new[] { 2, 3, 4, 5, 6 }, await xs.ToArrayAsync());
+            Assert.Equal([2, 3, 4, 5, 6], await xs.ToArrayAsync());
             Assert.Equal(new[] { 2, 3, 4, 5, 6 }, await xs.ToListAsync());
         }
 

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

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

+ 70 - 58
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Select.cs

@@ -26,7 +26,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Simple()
         {
-            var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerable([0, 1, 2]);
             var ys = xs.Select(x => (char)('a' + x));
 
             var e = ys.GetAsyncEnumerator();
@@ -39,7 +39,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Simple_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerableIList([0, 1, 2]);
             var ys = xs.Select(x => (char)('a' + x));
 
             var e = ys.GetAsyncEnumerator();
@@ -65,7 +65,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Indexed()
         {
-            var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerable([8, 5, 7]);
             var ys = xs.Select((x, i) => (char)('a' + i));
 
             var e = ys.GetAsyncEnumerator();
@@ -78,7 +78,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Indexed_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerableIList([8, 5, 7]);
             var ys = xs.Select((x, i) => (char)('a' + i));
 
             var e = ys.GetAsyncEnumerator();
@@ -104,7 +104,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Throws_Selector()
         {
-            var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerable([0, 1, 2]);
             var ys = xs.Select(x => 1 / x);
 
             var e = ys.GetAsyncEnumerator();
@@ -114,7 +114,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Throws_Selector_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerableIList([0, 1, 2]);
             var ys = xs.Select(x => 1 / x);
 
             var e = ys.GetAsyncEnumerator();
@@ -134,7 +134,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Indexed_Throws_Selector()
         {
-            var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerable([8, 5, 7]);
             var ys = xs.Select((x, i) => 1 / i);
 
             var e = ys.GetAsyncEnumerator();
@@ -144,7 +144,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Indexed_Throws_Selector_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerableIList([8, 5, 7]);
             var ys = xs.Select((x, i) => 1 / i);
 
             var e = ys.GetAsyncEnumerator();
@@ -164,7 +164,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_SelectSelect()
         {
-            var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerable([0, 1, 2]);
             var ys = xs.Select(i => i + 3).Select(x => (char)('a' + x));
 
             var e = ys.GetAsyncEnumerator();
@@ -177,7 +177,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_SelectSelect_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerableIList([0, 1, 2]);
             var ys = xs.Select(i => i + 3).Select(x => (char)('a' + x));
 
             var e = ys.GetAsyncEnumerator();
@@ -203,7 +203,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_SequenceIdentity()
         {
-            var xs = ToAsyncEnumerable(new[] { 1, 2, 3 });
+            var xs = ToAsyncEnumerable([1, 2, 3]);
             var ys = xs.Select(x => (char)('a' + x));
 
             await SequenceIdentity(ys);
@@ -212,7 +212,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_SequenceIdentity_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3]);
             var ys = xs.Select(x => (char)('a' + x));
 
             await SequenceIdentity(ys);
@@ -230,7 +230,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Indexed_SequenceIdentity()
         {
-            var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerable([8, 5, 7]);
             var ys = xs.Select((x, i) => (char)('a' + i));
 
             await SequenceIdentity(ys);
@@ -239,7 +239,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_Indexed_SequenceIdentity_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerableIList([8, 5, 7]);
             var ys = xs.Select((x, i) => (char)('a' + i));
 
             await SequenceIdentity(ys);
@@ -257,7 +257,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_IList_Count()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.Select(x => x * 2);
 
             Assert.Equal(5, await ys.CountAsync());
@@ -266,7 +266,7 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_IList_ToList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.Select(x => x * 2);
 
             Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToListAsync());
@@ -275,10 +275,10 @@ namespace Tests
         [Fact]
         public async Task Select_Sync_IList_ToArray()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.Select(x => x * 2);
 
-            Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToArrayAsync());
+            Assert.Equal([2, 4, 6, 8, 10], await ys.ToArrayAsync());
         }
 
         [Fact]
@@ -293,7 +293,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Simple()
         {
-            var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerable([0, 1, 2]);
             var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
 
             var e = ys.GetAsyncEnumerator();
@@ -306,7 +306,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Simple_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerableIList([0, 1, 2]);
             var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
 
             var e = ys.GetAsyncEnumerator();
@@ -332,7 +332,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Indexed()
         {
-            var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerable([8, 5, 7]);
             var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
 
             var e = ys.GetAsyncEnumerator();
@@ -345,7 +345,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Indexed_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerableIList([8, 5, 7]);
             var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
 
             var e = ys.GetAsyncEnumerator();
@@ -371,7 +371,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Throws_Selector()
         {
-            var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerable([0, 1, 2]);
             var ys = xs.SelectAwait(x => new ValueTask<int>(1 / x));
 
             var e = ys.GetAsyncEnumerator();
@@ -381,7 +381,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Throws_Selector_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerableIList([0, 1, 2]);
             var ys = xs.SelectAwait(x => new ValueTask<int>(1 / x));
 
             var e = ys.GetAsyncEnumerator();
@@ -401,7 +401,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Indexed_Throws_Selector()
         {
-            var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerable([8, 5, 7]);
             var ys = xs.SelectAwait((x, i) => new ValueTask<int>(1 / i));
 
             var e = ys.GetAsyncEnumerator();
@@ -411,7 +411,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Indexed_Throws_Selector_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerableIList([8, 5, 7]);
             var ys = xs.SelectAwait((x, i) => new ValueTask<int>(1 / i));
 
             var e = ys.GetAsyncEnumerator();
@@ -431,7 +431,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_SelectSelect()
         {
-            var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerable([0, 1, 2]);
             var ys = xs.SelectAwait(i => new ValueTask<int>(i + 3)).SelectAwait(x => new ValueTask<char>((char)('a' + x)));
 
             var e = ys.GetAsyncEnumerator();
@@ -444,7 +444,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_SelectSelect_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerableIList([0, 1, 2]);
             var ys = xs.SelectAwait(i => new ValueTask<int>(i + 3)).SelectAwait(x => new ValueTask<char>((char)('a' + x)));
 
             var e = ys.GetAsyncEnumerator();
@@ -470,7 +470,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_SequenceIdentity()
         {
-            var xs = ToAsyncEnumerable(new[] { 1, 2, 3 });
+            var xs = ToAsyncEnumerable([1, 2, 3]);
             var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
 
             await SequenceIdentity(ys);
@@ -479,7 +479,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_SequenceIdentity_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3]);
             var ys = xs.SelectAwait(x => new ValueTask<char>((char)('a' + x)));
 
             await SequenceIdentity(ys);
@@ -497,7 +497,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Indexed_SequenceIdentity()
         {
-            var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerable([8, 5, 7]);
             var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
 
             await SequenceIdentity(ys);
@@ -506,7 +506,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_Indexed_SequenceIdentity_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerableIList([8, 5, 7]);
             var ys = xs.SelectAwait((x, i) => new ValueTask<char>((char)('a' + i)));
 
             await SequenceIdentity(ys);
@@ -524,7 +524,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_IList_Count()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
 
             Assert.Equal(5, await ys.CountAsync());
@@ -533,7 +533,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_IList_ToList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
 
             Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToListAsync());
@@ -542,10 +542,10 @@ namespace Tests
         [Fact]
         public async Task SelectAwait_IList_ToArray()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.SelectAwait(x => new ValueTask<int>(x * 2));
 
-            Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToArrayAsync());
+            Assert.Equal([2, 4, 6, 8, 10], await ys.ToArrayAsync());
         }
 
 #if !NO_DEEP_CANCELLATION
@@ -562,7 +562,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Simple()
         {
-            var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerable([0, 1, 2]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
 
             var e = ys.GetAsyncEnumerator();
@@ -575,7 +575,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Simple_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerableIList([0, 1, 2]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
 
             var e = ys.GetAsyncEnumerator();
@@ -601,7 +601,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Indexed()
         {
-            var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerable([8, 5, 7]);
             var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
 
             var e = ys.GetAsyncEnumerator();
@@ -614,7 +614,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Indexed_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerableIList([8, 5, 7]);
             var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
 
             var e = ys.GetAsyncEnumerator();
@@ -640,7 +640,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Throws_Selector()
         {
-            var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerable([0, 1, 2]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
 
             var e = ys.GetAsyncEnumerator();
@@ -650,7 +650,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Throws_Selector_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerableIList([0, 1, 2]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
 
             var e = ys.GetAsyncEnumerator();
@@ -670,7 +670,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Indexed_Throws_Selector()
         {
-            var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerable([8, 5, 7]);
             var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<int>(1 / i));
 
             var e = ys.GetAsyncEnumerator();
@@ -680,7 +680,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Indexed_Throws_Selector_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerableIList([8, 5, 7]);
             var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<int>(1 / i));
 
             var e = ys.GetAsyncEnumerator();
@@ -700,7 +700,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_SelectSelect()
         {
-            var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerable([0, 1, 2]);
             var ys = xs.SelectAwaitWithCancellation((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
 
             var e = ys.GetAsyncEnumerator();
@@ -713,7 +713,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_SelectSelect_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
+            var xs = ToAsyncEnumerableIList([0, 1, 2]);
             var ys = xs.SelectAwaitWithCancellation((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
 
             var e = ys.GetAsyncEnumerator();
@@ -739,7 +739,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_SequenceIdentity()
         {
-            var xs = ToAsyncEnumerable(new[] { 1, 2, 3 });
+            var xs = ToAsyncEnumerable([1, 2, 3]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
 
             await SequenceIdentity(ys);
@@ -748,7 +748,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_SequenceIdentity_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
 
             await SequenceIdentity(ys);
@@ -766,7 +766,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Indexed_SequenceIdentity()
         {
-            var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerable([8, 5, 7]);
             var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
 
             await SequenceIdentity(ys);
@@ -775,7 +775,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_Indexed_SequenceIdentity_IList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
+            var xs = ToAsyncEnumerableIList([8, 5, 7]);
             var ys = xs.SelectAwaitWithCancellation((x, i, ct) => new ValueTask<char>((char)('a' + i)));
 
             await SequenceIdentity(ys);
@@ -793,7 +793,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_IList_Count()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
 
             Assert.Equal(5, await ys.CountAsync());
@@ -802,7 +802,7 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_IList_ToList()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
 
             Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToListAsync());
@@ -811,15 +811,21 @@ namespace Tests
         [Fact]
         public async Task SelectAwaitWithCancellation_IList_ToArray()
         {
-            var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3, 4, 5 });
+            var xs = ToAsyncEnumerableIList([1, 2, 3, 4, 5]);
             var ys = xs.SelectAwaitWithCancellation((int x, CancellationToken ct) => new ValueTask<int>(x * 2));
 
-            Assert.Equal(new[] { 2, 4, 6, 8, 10 }, await ys.ToArrayAsync());
+            Assert.Equal([2, 4, 6, 8, 10], await ys.ToArrayAsync());
         }
 
 #endif
 
+#if NET8_0_OR_GREATER
+#pragma warning disable CA1859 // Use specific iterator type for perf. Not really necessary for tests.
+#endif
         private static IAsyncEnumerable<int> ToAsyncEnumerable(int[] xs) => new MyIterator(xs);
+#if NET8_0_OR_GREATER
+#pragma warning restore CA1859
+#endif
 
         private class MyIterator : IAsyncEnumerable<int>
         {
@@ -838,13 +844,19 @@ namespace Tests
 
                 public int Current => _parent._xs[_i];
 
-                public ValueTask DisposeAsync() => new ValueTask();
+                public ValueTask DisposeAsync() => new();
 
-                public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(++_i < _parent._xs.Length);
+                public ValueTask<bool> MoveNextAsync() => new(++_i < _parent._xs.Length);
             }
         }
 
+#if NET8_0_OR_GREATER
+#pragma warning disable CA1859 // Use specific iterator type for perf. Not really necessary for tests.
+#endif
         private static IAsyncEnumerable<int> ToAsyncEnumerableIList(int[] xs) => new MyIteratorIList(xs);
+#if NET8_0_OR_GREATER
+#pragma warning restore CA1859
+#endif
 
         private class MyIteratorIList : IAsyncEnumerable<int>, IList<int>
         {
@@ -889,9 +901,9 @@ namespace Tests
 
                 public int Current => _parent._xs[_i];
 
-                public ValueTask DisposeAsync() => new ValueTask();
+                public ValueTask DisposeAsync() => new();
 
-                public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(++_i < _parent._xs.Length);
+                public ValueTask<bool> MoveNextAsync() => new(++_i < _parent._xs.Length);
             }
         }
     }

+ 1 - 1
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/Single.cs

@@ -29,7 +29,7 @@ namespace Tests
         [Fact]
         public async Task SingleAsync_Empty_IList()
         {
-            var res = new int[0].ToAsyncEnumerable().SingleAsync();
+            var res = Array.Empty<int>().ToAsyncEnumerable().SingleAsync();
             await AssertThrowsAsync<InvalidOperationException>(res.AsTask());
         }
 

Некоторые файлы не были показаны из-за большого количества измененных файлов