views:

1973

answers:

10

.NET offers a generic list container who's 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.

+19  A: 

Use the constructor which takes an int ("capacity") as an argument:

List<string> = new List<string>(10);

EDIT: I should add that I agree with Frederik. You are using the List in a way that goes against the entire reasoning behind using it in the first place.

EDIT2:

EDIT 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.

Why would anyone need to know the size of a List with all null values? If there are no real values in the list, I would expect the length to be 0. Anyhow, the fact that this is cludgy demonstrates that it is going against the intended use of the class.

Ed Swangren
+1, he wants an Array.
Karl
+8  A: 

Why are you using a List if you want to initialize it with a fixed value ? I can understand that -for the sake of performance- you want to give it an initial capacity, but isn't one of the advantages of a list over a regular array that it can grow when needed ?

When you do this:

List<int> = new List<int>(100);

You create a list whose capacity is 100 integers. This means that your List won't need to 'grow' until you add the 101th item. The underlying array of the list will be initialized with a length of 100.

Frederik Gheysels
"Why are you using a List if you want to initialize it with a fixed value" A good point.
Ed Swangren
+3  A: 

Initializing the contents of a list like that isn't really what lists are for. Lists are designed to hold objects. If you want to map particular numbers to particular objects, consider using a key-value pair structure like a hash table or dictionary instead of a list.

Welbog
You might be the only sane and rational person here.
Geoffrey Chetwood
+5  A: 

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.

Jon Skeet
I just wrote this same chunk of code. Damn your speedier fingers!
plinth
+1  A: 

It really depends on why you want to initialize it. I'm not sure initializing it with a certain number of empty or null elements is useful. The advantage of lists are that they can grow as needed.

The list constructor takes a capacity parameter which can be used to initially fill it.

List<string> = new List<string>(10);
CShipley
A: 
  string [] temp = new string[] {"1","2","3"};
        List<string> temp2 = temp.ToList();
Henk
How about List<string> temp2 = new List<string>(temp);Like the OP already suggested.
Ed Swangren
Ed - this one actually does answer the question - which is not about capacity.
Boaz
But the OP already stated that he did not like this solution.
Ed Swangren
A: 

If you want to initialize the list with N elements of some fixed value:

public List<T> InitList<T>(int count, T initValue)
{
  return Enumerable.Repeat(initValue, count).ToList();
}
David B
See John Skeet's answer for concern over buffer resizing by this technique.
David B
+1  A: 

You seem to be emphasizing the need for a positional association with your data, so wouldn't an associative array be more fitting?

Dictionary<int, string> foo = new Dictionary<int, string>();
foo[2] = "string";
Greg D
+1  A: 
List<string> L = new List<string> ( new string[10] );
A: 

If I'm reading this correctly, there is no built-in way to initialize a list to a specific size without manually adding blank values, is that correct?

I've encountered a situation where this is necessary. I'm VERY new to JSON serialization so if there is a better way to do this, PLEASE let me know!

I am using CollectionDataContractJsonSerializer to serialize a collection to JSON, however this collection needs to be an array of int items of a fixed size. the CollectionDataContract attribute needs to apply to a class, and I can't inherit from an array. Instead I'm inheriting from List and doing a for loop up to the Capacity size, adding default values (0) to the collection in the constructor.

is there a better way to do this? many thanks!

Josh