14

When I initialize an array and access elements using the indexer, that works just fine:

object[] temp = new object[5];
temp[0] = "bar";

Now I would expect the same to work for a List<T>, given you can initialize it by passing the capacity to the constructor:

List<object> temp = new List<object>(5);
temp[0] = "bar";

This last line however throws the following exception:

Index was out of range. Must be non-negative and less than the size of the collection

Why does this happen for the List<T> type, but not for the array? Since arrays are just lower level abstractions for collections for the CLR, then why does this exception occur?


Original question by Awais Mahmood.

Community
  • 1
  • 1
O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114
  • You can find all of the meta discussion about this question [over here](http://meta.stackoverflow.com/questions/315643/are-broad-unspecific-questions-about-entire-topic-areas-preferred-over-specific). – Robert Harvey Jan 28 '16 at 16:11
  • 1
    @RobertHarvey: Thank you - nonetheless, I have re-added a brief remark about the original author, as I do not want to look like a plagiarizer who copies other people's question without giving credit. – O. R. Mapper Jan 28 '16 at 18:42

1 Answers1

15

Short answer: Because the 5 does very different things.

Long answer:

When initializing an array, you set its size, and that size is fixed. The array cannot grow or shrink later on. Therefore,

object[] temp = new object[5];

means that you create a new array with 5 elements. Hence, you can access these elements right after creating the array.

For lists, size is variable. Instances of the List<T> class internally use an array for storing their items, and when you add or remove items in the list, that array gets replaced with a bigger or smaller array. On each of these occasions, all items that remain in the list get copied from the previous array to the new one. As this is quite a costly operation, the internal array has some overhead of unused items. As long as items are added to the list and the size of that internal array is not exceeded, the array does not need to be replaced.

The 5 that you pass to the constructor of the list is the initial size of that internal array:

List<object> temp = new List<object>(5);

That means, the list you create has zero elements (hence the exception), but the internal array is initialized to a size of 5, so you can add 5 elements without requiring the internal array to be replaced.

O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114
  • 1
    @SririamSakthivel: Thank you for your edit. However, I truly think *replaced* makes more sense than *resized*. The very point of the answer is that arrays do *not* get *resized*, but that there is an internal array in a list that gets *replaced* with a new, bigger or smaller array instance. – O. R. Mapper Jan 28 '16 at 12:43
  • 1
    Maybe you should mention that to fix his List code, he should change the line from `temp[i] = criteria[i + 1].ToString();` to `temp.Add(criteria[i + 1].ToString());` – user2023861 Jan 28 '16 at 21:17