Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What version of List constructor is used when defining it with a collection expression?

Tags:

c#

.net

I have a list of fixed count of items, unfortunately I have to use a list instead of an array due to external APIs. I am aware that this list will have a fixed size of X, so when instantiating a list, I use the

public List(int capacity)

constructor.

Now, I would love to switch to collection expression and let the compiler do the heavy lifting for me, and also having cleaner code, but, which version of List constructor will the collection expression compile to? Specific capacity or just random big?

like image 547
John Demetriou Avatar asked Oct 11 '25 12:10

John Demetriou


1 Answers

which version of List constructor will the collection expression compile to?

This depends on which compiler and runtime, and the exact syntax used. If you have a recent compiler (I believe from C# 12 / .NET 8 onwards, but I haven't checked), then the compiler goes far out of it's way to be efficient here. Let's take the example (from @canton7's comment above):

List<int> list = [1, 2, 3, 4, 5];

Assuming this is used against a recent runtime, this goes to great lengths to be efficient; not only using new List<int>(5), but also using nefarious CollectionsMarshal techniques to push the underlying values as efficiently as possible - bypassing the usual list.Add(...) boilerplate, since it understands what is going to happen:

int num = 5;
List<int> list = new List<int>(num);
CollectionsMarshal.SetCount(list, num);
Span<int> span = CollectionsMarshal.AsSpan(list);
int num2 = 0;
span[num2] = 1;
num2++;
span[num2] = 2;
num2++;
span[num2] = 3;
num2++;
span[num2] = 4;
num2++;
span[num2] = 5;
num2++;
List<int> list2 = list;

If the necessary CollectionsMarshal methods aren't available, it will still use the correct initial size.

If we use the older syntax:

var list = new List<int> { 1, 2, 3, 4, 5 };

then this uses the default new List<int>() constructor without the size, and just uses .Add():

List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
List<int> list2 = list;

This may be due to how the language specification defines this to behave, or may just be to avoid unexpected surprises. You can improve that by manually specifying the size:

var list = new List<int>(5) { 1, 2, 3, 4, 5 };

but then you need to ensure that you're correct!

So: prefer [...] syntax over {...} syntax, and yes: you should be fine.

like image 72
Marc Gravell Avatar answered Oct 14 '25 02:10

Marc Gravell