A new feature is hitting C# 12 and it is called Collection literals. In this blog post, I will show you what it is and how it works.
Summary
The easiest to show what the new feature does is to give the motivation.
Collection literals 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.
The motivation is to have a unified and easy API to interact with collections. Here a live example:
List<int> start = [1, 2, 3];
Span<int> end = [5, 6, 7];
var all = (List<int>)[..start, 4, ..end];
// [1, 2, 3, 4, 5, 6, 7]
all.Dump();
We can see that we easily can create a collection and even "merge" multiple lists and simple elements into one list via the same syntax. Of course this is a new syntax and therefore has a certain risk to it. But on the plus side is that we have an aligned way of doing things. Also dicitionaries are supported in the near future:
// Currently not implemented but targeted for C#12
Dictionary<int, string> myMap = [1: "one", 2: "two"];
As you might read from the comments, the day I wrote that article the feature is not working but it is targeted for C# 12. That said as this is still in preview, it could be that the feature will not make it into the final release or will change. There are still some open points the team wants to tackle.
Custom implementation
It is also planned to add a way for your custom collections to support this feature:
[CollectionBuilder(typeof(ImmutableHashSet), "Create")]
public class ImmutableHashSet<T> { /*...*/ }
public static class ImmutableHashSet
{
public static ImmutableHashSet<T> Create<T>(ReadOnlySpan<T> values);
}
ImmutableHashSet<int> values = [1, 2, 3];
Another interesting way to make it work is:
[CollectionBuilder(typeof(ImmutableHashSet<>), ".ctor")]
public class ImmutableHashSet<T>
{
public ImmutableHashSet(ReadOnlySpan<T> values);
}
// code:
ImmutableHashSet<int> values = [1, 2, 3];
Resources
- The original proposal: Collection literals on GitHub