What are the differences between an Array and List in C#? An Array and List both serve as collections of values, but they differ in how they store their contents in memory and how they can be accessed. In order to use either effectively, you'll need to understand the differences between them so that you can pick the right one for your purposes.
First let's quickly review the basic concepts of what is an Array and what is a List:
What is an Array?
An Array is a set or sequence of elements and can be of different types (string, double, int, float, etc…) but they have to be of a single type. It allows to store many variables of the same type inside a single variable.
Let's imagine that we have a calendar that stores the holidays
, then, we are storing several holidays in a single variable.
string[] holidays = {"christmas", "easter", "new year"};
One of their main characteristics is that they always have a defined length, which is equal to the number of elements that fit inside.
What is an List?
A List is a group of objects and can be of different types (they do not have to be all of the same type as in the Array).
Let's see what the example of holidays in a List would look like:
var holidays = new List<string>();
days.Add("christmas");
days.Add("easter");
days.Add("new year");
The main characteristic of a List (difference with an Array) is that its length does not have to be defined, they can have a variable length.
Now you will tell me that I have only come here to explain that difference but no, let's start slowly:
What is memory usage and what types are there?
Memory explained in a very basic way, is the space in which the application "remembers" information or data that is used over a period of time. It is like the human memory, which retains things.
When we talk about memory usage, it is often confused with the size of the memory it uses on the disk and this is where doubts arise.
Let's quickly review the 2 types of memory that exist:
Static memory: The type of memory that is defined at compile time. This memory space is reserved for a variable and cannot be changed at runtime.
Dynamic memory: The type of memory used at runtime. This memory space is also reserved for a variable, but in this case it can be modified at run time.
Being more or less clear about the difference between static memory and dynamic memory. For this comparison between Array and List, let's focus on the one we are interested in right now: Dynamic memory.
Explaining dynamic memory (Array)
Suppose we have space in dynamic memory, let's think in cells and each cell stores a value and now, imagine that we already have several cells occupied by something. Let's take out Paint:
Now, let's imagine that we want to add to the memory our previous Array, the one with the holidays:
string[] holidays = {"christmas", "easter", "new year"};
The result would be something like this:
Well, all good but… what if I wanted to add another element to the Array? For example fallas (it's a typical Spanish holiday).
If at first you think it would go in the next cell (after the first X, below Christmas), you failed.
This is the main characteristic of the Array, it must always be continuous in memory. That is, all the elements of the Array must be next to each other, they cannot be separated.
So, if we add the fallas holiday, the result would be as follows:
📚Remember: The Array will always look for the required number of free cells next to each other to place their values there.
Now, having clear how an Array works in memory, let's see how a List works in memory.
Explaining dynamic memory (List)
Lists work with nodes, a node consists of a value and a pointer to the next node. There are also start and end pointers, which means that if I want the value new year
(taking the example of holidays), I would simply follow the pointers until I get to it:
var holidays = new List<string>();
days.Add("christmas");
days.Add("easter");
days.Add("new year");
Let's imagine in this scheme of how the Lists work, we want to add the holiday of fallas. Well, simply the pointer of the last element (that is new year
) will point to a new element (that will be fallas
) and the pointer of this last one, will point to the final pointer. Let's see the example:
Now, what would it be like to add a new element (fallas
) in memory of a list? Let's remember our scheme:
And in this case, yes, as list elements work with pointers pointing to the next element, the new element could go in the next free cell. They do not have to go one after the other. This is how it would look like:
📚Remember: The list can continue in the next free cell. The elements of a list do not need to be all together in a row.
Now, you know the differences between an Array and a List in terms of memory, but what about performance? I think you already have an idea but let's go a little deeper.
Performance benchmark: Array vs List
Let's start with practice! We are going to have a class that is going to load a set of records inside a loop, little else:
The tests we will do will be the same for lists and arrays:
<int>
<object>
<long>
<ulong>
You can also run the test. I'm going to leave the Gist link so you can try it too (I don't embed the gist because it gets long): 🚀Array vs List benchmark
When running the test we found this:
Voilà, Arrays can be up to 97% faster than Lists (obvious, this is a synthetic test and in real tests the difference will be smaller).
I hope the explanation was clear, now you know the differences between an Array and a List both in terms of memory and performance! If you liked it, show it to me with liking and saving post so I can give you better content.
Top comments (3)
List does not work like that.
It wraps an array that is often a little bigger than needed.
When you .Add to a list, it checks the size of the array ...
If you don't believe me, check the source code.
github.com/dotnet/runtime/blob/mai...
I think you are confusing
List<T>
withLinkedList<T>
.Nice write up. But the behavior you described for List is the one for LinkedList