Julian
Julian

Reputation: 1294

Why is the .Count of a List<T>(Int32) with initial size 0?

Hi today I stumbled over a thing with the List<T>(Int32). I thought the behaviour would be the same in following examples:

1.

var myList = new List<string>(5);
myList[1] = string.Empty;

2.

var myArray= new string[5];
myArray[1] = string.Empty;

The first example fails and I get a 'System.ArgumentOutOfRangeException'. The second example works well.

So I tried .Count on the list and it says its 0, where as when I put .Length at the array it says 5.

In MSDN it says:

Initializes a new instance of the List class that is empty and has the specified initial capacity.

I thought this means the list has the initial size I pass in. Why isn't this the case?

Thanks in advance!

Upvotes: 4

Views: 781

Answers (2)

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64943

The initial capacity refers to the internal array storage maintained by the list.

If you expect to hold 100 items and you specify 100 as initial capacity, you avoid the overhead of the internal resizing of the array (well, actually the list avoids creating a new array and copy the values from the previous one...).

Maybe now you've realized that a list (and many other collection types) are just an abstraction of arrays to provide specific semantics: lists, sets, dictionaries...

For example, a list collection with 100 items of initial capacity might add items to an internal array which already has 100 indexes/slots:

int[] array1 = new int[100];
array1[0] = 1;
// until...
array1[99] = 2;

...while a one which doesn't provide a good capacity, it may need to internally handle the insertion of 100 items this way:

int[] array2 = new int[3];
array2[0] = 1;
array2[1] = 2;
array2[2] = 3;

int[] array3 = new int[6];
array2.CopyTo(array3);
array3[3] = 4;
array3[4] = 5;
array3[5] = 6;

int[] array4 = new int[9];
array3.CopyTo(array4);
array4[6] = 7;
array4[7] = 8;
array4[8] = 9;
// and so on...

The whole internal array as list's storage already does a minimum reservation, but this is just an implementation detail. If you already know how many items you're going to add to the list, it'll be better that you provide an initial capacity.

Note that the initial capacity doesn't fix the maximum capacity of the whole list. This would defeat the purpose and semantics of lists: a collection of objects ordered by inserting order (FIFO, first-in, first-out). Once the capacity has been reached, the internal array is resized again.

Also, since lists in the higher-level are described as just object collections, you can't expect that providing an initial capacity could provide access to the internal storage indexes. The fact that there's an internal array storing collection's object is an implementation detail, you need to rely on high-level details:

// Above reason is why you CAN'T access myList[1]
var myList = new List<string>(5);
myList[1] = string.Empty;

Further details

Hopefully, now most .NET Framework source code is available online. You can take a look at List<T> source code to check yourself how it works internally:

Upvotes: 7

Martheen
Martheen

Reputation: 5634

Count is how much elements actually in the list, Capacity is the size of the internal data structure. It's intended to handle large list that you already know the size beforehand, so it doesn't need repeated resizing when adding.

Upvotes: 10

Related Questions