Question

I know I can use a collection initializer to initialize a list:

var list = new List<string>
{
    "test string 1",
    "test string 2"
};

If I recall, this internally calls Add for each item.

Why is there not a constructor for List<T> that takes a params T[] items?

var list = new List<string>("test string 1", "test string 2");
Was it helpful?

Solution

The real reason is that the designers simply didn't feel that the benefit of this little bit of syntactic sugar was worth the effort of implementing or that it might cause some confusion.

There is a slight issue if you want create a List<int>. What should this mean?

var list = new List<int>(10);

Is that a new list with capacity 10, or a new list containing a single element, 10?

Spoiler, if you're not sure how the compiler will interpret it:

It will be treated as a capacity. If T is anything other than int, it will be treated as a single element. It would also be treated as a single item if you specify the parameter name—List<int>(items:10)

In any case, there's no reason you couldn't just write:

var list = new List<string>(new[] { "test string 1", "test string 2" });

This is exactly what the compiler would do if there had been a constructor that provided a params argument, and this is indeed slightly more efficient than the collection initializer. Having to type a few extra characters to accomplish this really isn't that big of a deal in the grand scheme of things.

OTHER TIPS

... because there isn't a compelling case to create one? In particular, there is no way of knowing that params was used as params, rather than just by passing a string[] in, so it wouldn't be able to trust that array as the backing array - so it would be an additional and unnecessary allocation of a vector. And the collection initializer syntax works pretty nicely. If you want it allocated at the correct size, you can always use:

var list = new List<string>(2)
{
    "test string 1",
    "test string 2"
};

although frankly, the number of times where this would be important is really small.

Actually, I spend a lot of time removing params usage. On a busy site, it is measurably painful (when used in a hot code path).

Because nobody implemented it.

Furthermore, it's unnecessary because of collection initializer syntax, which is roughly equivalent (see @p.s.w.g.'s answer)

But! Wait... I'm feeling so generous, so consider this a gift from me to you:

public class SpecialListJustForYou<T> : List<T>
{
    public SpecialListJustForYou(int capacity):base(capacity){}
    public SpecialListJustForYou(IEnumerable<T> collection):base(collection){}
    public SpecialListJustForYou():base(){}

    // and here's the magic!
    public SpecialListJustForYou(params T[] items) : base(items == null ? Enumerable.Empty<T>() : items.AsEnumerable()){}
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top