-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Compile collection expressions to using ImmutableArray when targeting read-only interfaces #78106
Comments
We could also consider expanding this proposal to replace the synthesized types that wrap a An additional benefit of using |
Could you show the debugger view of ImmutableArray for comparison? What is it about ImmutableArray that causes a nicer display than for a type we synthesize? |
I think the following emit strategy would be feasible:
|
What's nice is that strategies (1), (3), and (4) are already implemented. We just have to tell the lowering to use those strategies in the interface case. And for (1) we are already telling lowering to do that. |
@RikkiGibson Awesome! |
Summary
I propose that, in situations when a collection expression is currently compiled to using a compiler-generated collection type to wrap an array in a read-only fashion, that code should construct a
System.Collections.Immutable.ImmutableArray<T>
instead and not rely on a compiler-generated type.Background and Motivation
At the moment, collection expressions that target read-only interfaces like
IEnumerable<T>
orIReadOnlyCollection<T>
use a compiler-generated type that implements the desired interface, and a few other likely useful ones:However, this implementation prevents certain optimizations which test the resulting instance for a more concrete type, such as what
TryGetSpan
in LINQ does (testing forT[]
andList<T>
). Because there is no interface that the generated class could use to implement anAsSpan
method, there is no way consumers of such instances could get a contiguous view over the items, and use that for efficient enumerating.To improve this situation, a standard type like
ImmutableArray<T>
could be used in this case instead. This type implements all of the interfaces currently implemented by the synthesizedReadOnlyArray
(and some more) and is structurally equivalent too ‒ all it does is wrapping an array. Using this as the concrete implementation for such collection expressions allows consumers to test forImmutableArray<T>
and callAsSpan
easily:Using
ImmutableArray<T>
here as an implementation detail is allowed by the language, which permits free choice of either a pre-existing type or a compiler-generated one, as long it implements the interfaces correctly, and does not allow mutation.Proposed Feature
The compiler should construct an
ImmutableArray<T>
from a collection expression if all of these conditions are true:IEnumerable<T>
,IReadOnlyCollection<T>
,IReadOnlyList<T>
).ReadOnlySingleElementList
is not picked instead).System.Collections.Immutable.ImmutableArray<T>
is available and usable as a collection expression target. Ideally, this should lead toImmutableCollectionsMarshal.AsImmutableArray
.This should also apply to
params
(and potentially other future collection expressions-like contexts).Alternative Designs
AsSpan
in the generated class. While such an interface could be useful on its own, it would not be available for older .NET versions, whereasImmutableArray<T>
is already available and readily usable.string
is considered forIEnumerable<char>
).The text was updated successfully, but these errors were encountered: