0

Why do I need to use the Add() to add elements to a List. Why can't I use indexing and do it. When I traverse the elements through the List I do it using the help of indexes.

int head = -1;
List<char> arr = new List<char>();
public void push(char s)
{
    ++head;
    arr[head] = s;//throws runtime error.
    arr.Add(s);
}

It doesn't throw any error during compile time. But throws an error at runtime stating IndexOutOfRangeException.

CSDev
  • 3,177
  • 6
  • 19
  • 37
CodeOfLife
  • 295
  • 2
  • 11

4 Answers4

1
++head; 
arr[head] = s;

This attempts to set element 1 of the list to s, but there is no element 1 yet because you've not added anything, or set the length of the list.

When you create an array, you define a length, so each item has a memory address that can be assigned to.

Lists are useful when you don't know how many items you're going to have, or what their index is going to be.

Robin Bennett
  • 3,192
  • 1
  • 8
  • 18
  • So when i traverse like this "arr[i]" in a list ,so it means that this is the first elemenst in a list,whereas in an array it means that at memory location arr[i],this is the element??Please clear my doubt – CodeOfLife Aug 01 '19 at 14:35
  • When you access an item by index, arrays and lists work the same. They're both lists of pointers to memory addresses. – Robin Bennett Aug 01 '19 at 14:41
  • Does this also mean that lists also store data in a contiguous block of memory?? – CodeOfLife Aug 01 '19 at 14:43
  • 1
    I doubt it, C# doesn't expose it's memory management, but if you add and remove stuff it's bound to get fragmented. Even with an array of objects, the list of pointers might be contiguous, but those pointers could point anywhere. – Robin Bennett Aug 01 '19 at 15:57
1

Arrays are fixed sizes. Once you allocate them, you can not add or remove "slots" from it. So if you need it to be bigger, you need to:

  1. Detect that you need a bigger array.
  2. Allocate a new, bigger array
  3. copy all existing values to teh new, bigger array
  4. start using the bigger array from now on everywhere

All that Lists do is automate that precise process. It will automatically detect that it needs to increase during Add() and then do step 2-4 automagically. It is even responsible to pick the initial size and by how much to grow it (to avoid having to grow to often.

They could in theory jsut react to List[11000] by growing the size to 11000. But chances are very big, that this value is a huge mistake. And preventing the Progarmmer from doing huge mistakes is what half the classes and compiler rules (like strong typisation) are there for. So they force you to use Add() so such a mistake can not happen.

Christopher
  • 9,634
  • 2
  • 17
  • 31
1

Actually calling myArray[2] does not add the element, but just assigns the object to the specified index within the array. If the array´s size is less you´d get an IndexOutOfBoundsException, as in a list<T> also. So also in case of an array using the indexer assumes you actually have that many elements:

var array = new int[3];
array[5] = 4; // bang

This is because arrays have a fixed size which you can´t change. If you assign an object to an index greater the arrays size you get the exat same exception as for a List<T> also, there´s no difference here.

The only real difference here is that when using new array[3] you have an array of size 3 with indices up to 2 and you can call array[2]. However this would just return the default-value - in case of int this is zero. When using new List<int>(3) in contrast you don´t have actually three elements. In fact the list has no items at all and calling list[2] throws the exception. The parameter to a list is just the capacity, which is a parameter for the runtime to indicate when the underlying array of a list should be resized - an ability your array does not even have.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • I understood why i can't store elemenst in the same way as i do in an array.Does lists also store data in a continuous block of memory??If its an array then to find any element i take constant time because i know the first index and since its a continuous block of memory so i can calculate for element at any position.Can you explain me how traversing works for a list? – CodeOfLife Aug 01 '19 at 14:47
  • Does it take constant time to find an element of a list or not??I am still wondering about this. – CodeOfLife Aug 01 '19 at 14:52
  • 1
    As a list is just a wrapper around an array, accessing an element by index yields to accessing the underlying array by index. So the time should be fairly identical. – MakePeaceGreatAgain Aug 01 '19 at 14:56
  • I did get a lot of useful information from this question and my doubt is clear because of you and Robin.Thanks. – CodeOfLife Aug 01 '19 at 14:58
0

A list is an array wrapper, where the internal array size is managed by its methods. The constructor that takes a capacity simply creates an array of that size internally, but the count property (which reflects the count elements that has been added) will be zero. So in essence, zero slots in the array has been assigned a value.

The size of an array is managed by you the programmer. That is why you have to call static methods like System.Array.Resize (notice that the array argument is ref), if you want to change an array yourself. That method allocates a new chunk of memory for the new size.

So to sum up, the list essentially manages an array for you, and as such, the tradeoff is that you can only access as many array-like slots as has been added to it.

Rob
  • 181
  • 5