Skip to content

Conversation

@idg10
Copy link
Collaborator

@idg10 idg10 commented Nov 19, 2025

Resolves #2291

Earlier previews continued to define an AsyncEnumerable class in System.Linq.Async's public API. This is OK for extension methods—the compiler doesn't mind if multiple identically-named classes exist and they all provide extension methods for the same interface, as long as there's no ambiguity as to which particular method is being used.

However, this caused direct invocation of static methods such as AsyncEnumerable.Range(1, 10) to fail. Even though System.Linq.Async no longer defines this method, the compiler still reports an ambiguity error. And that's because even though there's only one AsyncEnumerable.Range, there were two AsyncEnumerable classes. (The one in System.Linq.Async, and the new one in System.Linq.AsyncEnumerable.)

We need to retain AsyncEnumerable in the runtime assemblies for binary compatibility. But in the public-facing API, the only reason we were continuing to define this type was so we could apply [Obsolete] attributes to the AsyncEnumerable extension methods that have been replaced by something else (e.g. because names have changed), or that are being removed entirely (in the case of ToEnumerable, which should never have existed). This now puts those on a new AsyncEnumerableDeprecated class in the public-facing API.

(Unfortunately, AsyncEnumerable.Create is a casualty of this. It was the one non-extension public static method previously defined by AsyncEnumerable that didn't move into System.Linq.AsyncEnumerable. It's available as AsyncEnumerableEx.Create now in System.Interactive.Async, but it's not possible for us to provide an obsolete attribute that tells people this. Fortunately the method shouldn't really be used much because since .NET Core 3.0, language-level support for async iterators provides a better solution to the problem this method solves.)

@idg10 idg10 added this to the Ix 7.0 milestone Nov 19, 2025
@idg10 idg10 self-assigned this Nov 19, 2025
@idg10 idg10 requested a review from Copilot November 19, 2025 14:59
Copilot finished reviewing on behalf of idg10 November 19, 2025 15:01
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR addresses a critical issue where having two AsyncEnumerable classes (one in System.Linq.Async and one in System.Linq.AsyncEnumerable) caused compiler ambiguity errors when directly invoking static methods like AsyncEnumerable.Range(1, 10). The solution renames the public-facing class in System.Linq.Async to AsyncEnumerableDeprecated while retaining the original name in runtime assemblies for binary compatibility.

Key changes:

  • Introduces conditional compilation to rename AsyncEnumerable to AsyncEnumerableDeprecated in reference assemblies
  • Moves AsyncEnumerable.Create method to AsyncEnumerableEx in System.Interactive.Async
  • Updates ADR documentation to reflect the accepted status and implementation details

Reviewed Changes

Copilot reviewed 71 out of 71 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
ApiApprovalTests.SystemInteractiveAsync.verified.cs Adds Create<T> method to the API approval test for System.Interactive.Async
Multiple Operator files (*.cs, *.tt) Adds conditional compilation directives to use AsyncEnumerableDeprecated in reference assemblies while keeping AsyncEnumerable in runtime assemblies
AsyncEnumerable.cs Wraps the entire class in #if INCLUDE_RELOCATED_TO_INTERACTIVE_ASYNC and updates comments explaining the breaking change
AsyncEnumerableEx.cs Adds the Create<T> method with supporting AnonymousAsyncEnumerable<T> class, previously in AsyncEnumerable
0002-System-Linq-Async-In-Net10.md Updates ADR from "Proposed" to "Accepted" and documents the implementation approach

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@idg10 idg10 merged commit 4c0104d into main Nov 20, 2025
5 checks passed
@idg10 idg10 deleted the feature/2291-syslinqasync-hide-asyncenumerable-type branch November 20, 2025 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

System.Linq.Async v7 causes ambiguity errors for non-extension methods

3 participants