-
Notifications
You must be signed in to change notification settings - Fork 779
Remove AsyncEnumerable from System.Linq.Async public API #2292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove AsyncEnumerable from System.Linq.Async public API #2292
Conversation
There was a problem hiding this 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
AsyncEnumerabletoAsyncEnumerableDeprecatedin reference assemblies - Moves
AsyncEnumerable.Createmethod toAsyncEnumerableExin 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.
Resolves #2291
Earlier previews continued to define an
AsyncEnumerableclass inSystem.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 thoughSystem.Linq.Asyncno longer defines this method, the compiler still reports an ambiguity error. And that's because even though there's only oneAsyncEnumerable.Range, there were twoAsyncEnumerableclasses. (The one inSystem.Linq.Async, and the new one inSystem.Linq.AsyncEnumerable.)We need to retain
AsyncEnumerablein 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 theAsyncEnumerableextension methods that have been replaced by something else (e.g. because names have changed), or that are being removed entirely (in the case ofToEnumerable, which should never have existed). This now puts those on a newAsyncEnumerableDeprecatedclass in the public-facing API.(Unfortunately,
AsyncEnumerable.Createis a casualty of this. It was the one non-extension public static method previously defined byAsyncEnumerablethat didn't move intoSystem.Linq.AsyncEnumerable. It's available asAsyncEnumerableEx.Createnow inSystem.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.)