C# 12: Collection literals

6/17/2023
2 minute read

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

Less boilerplate code with the new primary constructor in C# 12

The new language feature "primary constructor" which will be released with C# 12 / .NET 8 this year (November 2023) allows you to remove some ceremonial code. Let's see how.

nameof get's a bit better in C# 12

The nameof operator is a great way to get the name of a variable, type, or member. With C# 12 it's getting even better. Let's see how.

C# 12: Primary Constructors

Another new C# 12 feature might drop soon and makes its debut with the next iteration: Primary Constructors.

The blog post will talk about what a Primary constructor is, why we already have it, and what the proposal tries to change. Exciting times are ahead of us!

An error has occurred. This application may no longer respond until reloaded. Reload x