Reputation: 1294
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
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;
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