Boaz Boaz - 3 months ago 15
C# Question

How to initialize a List<T> to a given size (as opposed to capacity)?

.NET offers a generic list container whose performance is almost identical (see Performance of Arrays vs. Lists question). However they are quite different in initialization.

Arrays are very easy to initialize with a default value, and by definition they already have certain size:

string[] Ar = new string[10];


Which allows one to safely assign random items, say:

Ar[5]="hello";


with list things are more tricky. I can see two ways of doing the same initialization, neither of which is what you would call elegant:

List<string> L = new List<string>(10);
for (int i=0;i<10;i++) L.Add(null);


or

string[] Ar = new string[10];
List<string> L = new List<string>(Ar);


What would be a cleaner way?

EDIT: The answers so far refer to capacity, which is something else than pre-populating a list. For example, on a list just created with a capacity of 10, one cannot do
L[2]="somevalue"


EDIT 2: People wonder why I want to use lists this way, as it is not the way they are intended to be used. I can see two reasons:


  1. One could quite convincingly argue that lists are the "next generation" arrays, adding flexibility with almost no penalty. Therefore one should use them by default. I'm pointing out they might not be as easy to initialize.

  2. What I'm currently writing is a base class offering default functionality as part of a bigger framework. In the default functionality I offer, the size of the List is known in advanced and therefore I could have used an array. However, I want to offer any base class the chance to dynamically extend it and therefore I opt for a list.


Answer

I can't say I need this very often - could you give more details as to why you want this? I'd probably put it as a static method in a helper class:

public static class Lists
{
    public static List<T> RepeatedDefault<T>(int count)
    {
        return Repeated(default(T), count);
    }

    public static List<T> Repeated<T>(T value, int count)
    {
        List<T> ret = new List<T>(count);
        ret.AddRange(Enumerable.Repeat(value, count));
        return ret;
    }
}

You could use Enumerable.Repeat(default(T), count).ToList() but that would be inefficient due to buffer resizing.

EDIT: As noted in comments, you could make Repeated use a loop to populate the list if you wanted to. That would be slightly faster too. Personally I find the code using Repeat more descriptive, and suspect that in the real world the performance difference would be irrelevant, but your mileage may vary.