[Proposal]: Collection expressions (VS 17.7, .NET 8) · Issue #5354 · dotnet/csharplang (original) (raw)
Collection expressions
- Proposed
- Specification: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-12.0/collection-expressions.md
- Prototype: Complete
- Implementation: In progress. Shipping everything but 'natural types' and 'dictionary literals' in C# 12.
Many thanks to those who helped with this proposal. Esp. @jnm2!
Summary
Collection expressions introduce a new terse syntax, [e1, e2, e3, etc]
, to create common collection values. Inlining other collections into these values is possible using a spread operator ..
like so: [e1, ..c2, e2, ..c2]
. A [k1: v1, ..d1]
form is also supported for creating dictionaries.
Several collection-like types can be created without requiring external BCL support. These types are:
- Array types, such as
int[]
. - Span and ReadOnlySpan.
- Types that support collection initializers, such as List and Dictionary<TKey, TValue>.
Further support is present for collection-like types not covered under the above, such as ImmutableArray, through a new API pattern that can be adopted directly on the type itself or through extension methods.
Motivation
- Collection-like values are hugely present in programming, algorithms, and especially in the C#/.NET ecosystem. Nearly all programs will utilize these values to store data and send or receive data from other components. Currently, almost all C# programs must use many different and unfortunately verbose approaches to create instances of such values. Some approaches also have performance drawbacks. Here are some common examples:
- Arrays, which require either
new Type[]
ornew[]
before the{ ... }
values. - Spans, which may use
stackalloc
and other cumbersome constructs. - Collection initializers, which require syntax like
new List<T>
(lacking inference of a possibly verboseT
) prior to their values, and which can cause multiple reallocations of memory because they use N.Add
invocations without supplying an initial capacity. - Immutable collections, which require syntax like
ImmutableArray.Create(...)
to initialize the values, and which can cause intermediary allocations and data copying. More efficient construction forms (likeImmutableArray.CreateBuilder
) are unweildy and still produce unavoidable garbage.
- Arrays, which require either
- Looking at the surrounding ecosystem, we also find examples everywhere of list creation being more convenient and pleasant to use. TypeScript, Dart, Swift, Elm, Python, and more opt for a succinct syntax for this purpose, with widespread usage, and to great effect. Cursory investigations have revealed no substantive problems arising in those ecosystems with having these literals built in.
- C# has also added list patterns in C# 10. This pattern allows matching and deconstruction of list-like values using a clean and intuitive syntax. However, unlike almost all other pattern constructs, this matching/deconstruction syntax lacks the corresponding construction syntax.
- Getting the best performance for constructing each collection type can be tricky. Simple solutions often waste both CPU and memory. Having a literal form allows for maximum flexibility from the compiler implementation to optimize the literal to produce at least as good a result as a user could provide, but with simple code. Very often the compiler will be able to do better, and the specification aims to allow the implementation large amounts of leeway in terms of implementation strategy to ensure this.
An inclusive solution is needed for C#. It should meet the vast majority of casse for customers in terms of the collection-like types and values they already have. It should also feel natural in the language and mirror the work done in pattern matching.
This leads to a natural conclusion that the syntax should be like [e1, e2, e3, e-etc]
or [e1, ..c2, e2]
, which correspond to the pattern equivalents of [p1, p2, p3, p-etc]
and [p1, ..p2, p3]
.
A form for dictionary-like collections is also supported where the elements of the literal are written as k: v
like [k1: v1, ..d1]
. A future pattern form that has a corresponding syntax (like x is [k1: var v1]
) would be desirable.
Detailed design
The content of the proposal has moved to proposals/collection-expressions.md. Further updates to the proposal should be made there.
Design meetings
https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-11-01.md#collection-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-03-09.md#ambiguity-of--in-collection-expressions
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-09-28.md#collection-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-04-03.md#collection-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-04-26.md#collection-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-05-03.md#collection-literal-natural-type
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-05-31.md#collection-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-06-05.md#collection-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-06-19.md#collection-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-07-12.md#collection-literals
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-09-18.md#collection-expression-questions
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-09-20.md#collection-expressions
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-09-25.md#defining-well-defined-behavior-for-collection-expression-types
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-09-27.md#collection-expressions
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-10-02.md#collection-expressions
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-10-11.md#collection-expressions
https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-11-15.md#nullability-analysis-of-collection-expressions
https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-01-10.md
https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-02-26.md#collection-expressions
Working group meetings
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2022-10-06.md
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2022-10-14.md
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2022-10-21.md
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2023-04-05.md
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2023-04-28.md
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2023-05-26.md
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2023-06-12.md
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2023-06-26.md
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2023-08-03.md
https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2023-08-10.md