Open terrajobst opened 3 days ago
Tagging subscribers to this area: @dotnet/area-system-collections See info in area-owners.md if you want to be subscribed.
LinkedList
HashSet SortedSet
Those three work just fine today. They don't need special support as they provide IEnumerable<T>
/Add
implementations and thus already supported collection initializers which then implicitly meant they supported collection expressions.
ISet
IReadOnlySet
The compiler today special-cases the core collection interfaces, e.g. IEnumerable<T>
, IList<T>
, IReadOnlyCollection<T>
, IReadOnlyList<T>
. I think we should keep the special-casing of these core interfaces together rather than having some on one plan and some on another. Additionally, if we implement these using a params ReadOnlySpan<T>
builder, in some situations the compiler will be forced to allocate temporary storage, whereas it could avoid that if it has special knowledge. My preference is for these to be special-cased in the compiler as with the other interfaces.
Queue
Set
These are reasonable. We wouldn't need to do anything special for them if they had Add
methods... which they do, they're just called Enqueue
and Push
, respectively, and thus not recognized by the compiler.
LinkedList HashSet SortedSet
Those three work just fine today. They don't need special support as they provide
IEnumerable<T>
/Add
implementations and thus already supported collection initializers which then implicitly meant they supported collection expressions.
Presumably though there is benefit in exposing span factories since they can be presized? Doesn't seem essential in any case.
Stack
values5 = [1, 2, 3];
One thing worth calling out about stacks specifically is that this expression would construct a collection that when enumerated returns 3, 2, 1
. That's probably obvious assuming the caller is aware that they're constructing a stack, but they might miss that detail in target-typed contexts, e.g. when passing a function parameter.
@stephentoub
LinkedList HashSet SortedSet
Those three work just fine today.
Odd; I thought I tested these before. At least LinkedList<T>
doesn't seem to work though (tested on .NET 9.0):
LinkedList<int> values0 = [1, 2, 3];
error: 'LinkedList
' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'LinkedList ' could be found (are you missing a using directive or an assembly reference?)
@stephentoub
The compiler today special-cases the core collection interfaces, e.g.
IEnumerable<T>
,IList<T>
,IReadOnlyCollection<T>
,IReadOnlyList<T>
. I think we should keep the special-casing of these core interfaces together rather than having some on one plan and some on another.
I assume you're suggesting the compiler special cases ISet<T>
and IReadOnlySet<T>
then?
At least LinkedList
doesn't seem to work though (tested on .NET 9.0):
You're right; it calls it AddLast.
I assume you're suggesting the compiler special cases ISet
and IReadOnlySet then?
Yes.
Presumably though there is benefit in exposing span factories since they can be presized?
It can help on that front but hurt on others, e.g. if you write:
IEnumerable<int> source = ...;
HashSet<int> set = [1, 2, .. source];
would having the Create(span) builder force the compiler to allocate an int[] to store all the inputs in order to pass that off to Create?
Yeah, I defined as span to let the compiler use a stackallocated temp rather than forcing it to construct a heap allocated array. Not sure that's sufficient. Does it need scopped
?
Yeah, I defined as span to let the compiler use a stackallocated temp rather than forcing it to construct a heap allocated array. Not sure that's sufficient. Does it need
scopped
?
It has to be a span right now; that's all the compiler/language recognizes as part of the builder pattern.
It doesn't need to be scoped. Scoped here is implicit as there's nowhere the span could be stored. If the return types here were ref structs, then scoped would be necessary to prevent the span from being stashed into the returned value.
Background and motivation
We allowed collection expressions for
IImmutableSet<T>
,IImmutableQueue<T>
, andIImmutableStack<T>
.It seems odd to not support it on these types:
LinkedList<T>
Stack<T>
Queue<T>
ISet<T>
)IReadOnlySet<T>
)We don't want to special case
ISet<T>
andIReadOnlySet<T>
as the compiler already special cases all the other standard corlib interfaces; we should file a work item to have the compiler handle these as well.API Proposal
It seems the design of
CollectionBuilderAttribute
requires a non-generic type; in order to avoid adding a bunch of types we could do the following:API Usage
Alternative Designs
No response
Risks
No response