-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
[API Proposal]: Allow collections expression for other collections #108457
Comments
Those three work just fine today. They don't need special support as they provide
The compiler today special-cases the core collection interfaces, e.g.
These are reasonable. We wouldn't need to do anything special for them if they had |
Presumably though there is benefit in exposing span factories since they can be presized? Doesn't seem essential in any case.
One thing worth calling out about stacks specifically is that this expression would construct a collection that when enumerated returns |
Odd; I thought I tested these before. At least LinkedList<int> values0 = [1, 2, 3];
I assume you're suggesting the compiler special cases |
You're right; it calls it AddLast.
Yes. |
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 |
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. |
namespace System.Collections.Generic;
#if NECESSARY
public partial class CollectionExtensions
{
[EditorBrowsable(EditorBrowsableState.Never)]
public static LinkedList<T> CreateLinkedList<T>(params ReadOnlySpan<T> values);
[EditorBrowsable(EditorBrowsableState.Never)]
public static Stack<T> CreateStack<T>(params ReadOnlySpan<T> values);
[EditorBrowsable(EditorBrowsableState.Never)]
public static Queue<T> CreateQueue<T>(params ReadOnlySpan<T> values);
}
[CollectionBuilder(typeof(CollectionExtensions), "CreateLinkedList")]
public partial class LinkedList<T>;
[CollectionBuilder(typeof(CollectionExtensions), "CreateStack")]
public partial class Stack<T>;
[CollectionBuilder(typeof(CollectionExtensions), "CreateQueue")]
public partial class Queue<T>;
#else
public partial class Queue<T>
{
public Queue<T>(ReadOnlySpan<T> items);
}
public partial class Stack<T>
{
public Stack<T>(ReadOnlySpan<T> items);
}
public partial class LinkedList<T>
{
public LinkedList<T>(ReadOnlySpan<T> items);
}
#endif |
@terrajobst would it be possible to also support Unless I'm missing something, there's no other concrete type one could use in quite the same way here 🥲 The proposal would be like this: public partial class CollectionExtensions
{
[EditorBrowsable(EditorBrowsableState.Never)]
public static ReadOnlyCollection<T> CreateReadOnlyCollection<T>(params ReadOnlySpan<T> values);
}
[CollectionBuilder(typeof(CollectionExtensions), "CreateReadOnlyCollection")]
public partial class ReadOnlyCollection<T>; I'm happy to create a separate issue if needed, unless we can just easily tie this one to this proposal? |
A separate proposal would makes because |
ROC is an example of where it'd be nice to have a builder pattern that supports ownership transfer of an array or list. Without that, the compiler is likely to need to allocate storage (unless the size is known at compile time), and then the implementation of the builder will need to allocate the array again. |
Sure. We'd be happy if this came over to csharplang as a "future improvements on collection expressions" feature. If you guys are asking, then that carries a lot of weight |
I've created #110161 for now. With the proposed API taking a span, there should be no temporary allocations when initializing a |
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
The text was updated successfully, but these errors were encountered: