Home > Back-end >  Why can't you access an element of a list at an index without previously using the Add method?
Why can't you access an element of a list at an index without previously using the Add method?

Time:12-05

Why doesn't this program work if the list has been made with a set size?

List<int> list = new List<int>(2);
list[0] = 1;
Console.WriteLine(list[0])

This is the error: System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index

CodePudding user response:

Because the list is empty. That's why there are no elements thus no range

CodePudding user response:

I think a bit more explanation is in order. You are thinking that the "2" parameter in the List constructor creates a list of size 2. It does not. It creates an empty list with a capacity of 2. What that means effectively is that it pre-allocates enough space for two elements in the list so that as you add more and more elements it doesn't have to create any new space. However, the list is still empty, it just has some unused slots.

The way this works is that the list has a certain capacity at the start, in your case two, so two "slots" are allocated for the elements, but the list is still empty. You add an element and it uses the first slot, you add another element and it takes the next slot, you add a third element, now it is out of slots, so it allocates more memory (4 slots for example) copies over the previous two into the first two slots of the new block, adds the new one into the third slot and now you have a capacity of 4 but a list of length 3.

Many years ago I had a problem with a production system that took forever to start up (though this was in C .) In the loading phase we were loading stuff from a database into a memory list. It contained about 100,000 items. However the capacity was just 10 initially. So it filled the first ten, when they were filled, it allocated 20 slots and copied over the first ten over to the new memory and released that memory for the first ten (the algorithm was that it doubled the capacity when it ran out), then repeated with 40, 80, 160 and so forth slots. You can see that it CONSTANTLY was allocating slots and copying the same memory bytes over and over and over again in an exponential fashion.

We set the capacity correctly at the beginning and it went from taking several hours to load to less than a second.

So when you are making a really big list which you are adding to piecemeal, it often is a good idea to set the capacity at the beginning if you can. (FWIW, in C this is not only slow but causes horrible memory fragmentation, which is much less of an issue in a garbage collected language like C#.)

  • Related