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");
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 thanint
, 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.
... 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).
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()){}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With