5

I'm learning C# and basically know the difference between arrays and Lists that the last is a generic and can dynamically grow but I'm wondering:

  • are List elements sequentially located in heap like array or is each element located "randomly" in a different locations?
  • and if that is true, does that affect the speed of access & data retrieval from memory?
  • and if that is true, is this what makes arrays a little faster than Lists?
iCantSeeSharp
  • 3,880
  • 4
  • 42
  • 65
Ramy Yousef
  • 2,982
  • 2
  • 25
  • 24
  • 2
    [Implementation detail.](http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx) – It'sNotALie. Aug 11 '13 at 10:50
  • possible duplicate of [Generics memory management](http://stackoverflow.com/questions/8678795/generics-memory-management) – James Aug 11 '13 at 10:52

2 Answers2

7

Let's see the second and the third questions first:

and if that true does that affect the speed of access & data retrieval from memory ?

and if that true is this what makes array little faster than list ?

There is only a single type of "native" collection in .NET (with .NET I mean the CLR, so the runtime): the array (technically, if you consider a string a type of collection, then there are two native types of collections :-) ) (technically part 2: not all the arrays you think that are arrays are "native" arrays... Only the monodimensional 0 based arrays are "native" arrays. Arrays of type T[,] aren't, and arrays where the first element doesn't have an index of 0 aren't) . Every other collection (other than the LinkedList<>) is built atop it. If you look at the List<T> with IlSpy you'll see that at the base of it there is a T[] with an added int for the Count (the T[].Length is the Capacity). Clearly an array is a little faster than a List<T> because to use it, you have one less indirection (you access the array directly, instead of accessing the array that accesses the list).

Let's see the first question:

does List elements sequentially located in heap like array or each element is located randomly in different locations?

Being based on an array internally, clearly the List<> memorizes its elements like an array, so in a contiguous block of memory (but be aware that with a List<SomeObject> where SomeObject is a reference type, the list is a list of references, not of objects, so the references are put in a contiguous block of memory (we will ignore that with the advanced memory management of computers, the word "contiguous block of memory" isn't exact", it would be better to say "a contiguous block of addresses") )

(yes, even Dictionary<> and HashSet<> are built atop arrays. Conversely a tree-like collection could be built without using an array, because it's more similar to a LinkedList)

Some additional details: there are four groups of instructions in the CIL language (the intermediate language used in compiled .NET programs) that are used with "native" arrays:

  • Newarr

  • Ldelem and family Ldelem_*

  • Stelem and family Stelem_*

  • ReadOnly (don't ask me its use, I don't know, and the documentation isn't clear)

if you look at OpCodes.Newarr you'll see this comment in the XML documentation:

// Summary:
//     Pushes an object reference to a new zero-based, one-dimensional array whose
//     elements are of a specific type onto the evaluation stack.
Community
  • 1
  • 1
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • What about a list of a value type like int, bool, ...? I mean, are arrays of integers also arrays of references? I'm not that sure. – Matías Fidemraizer Aug 11 '13 at 11:12
  • @MatíasFidemraizer No, `int[]` is a reference to a block of memory where all the `int`s are (plus some other ancillary things... but in the end it's a little opaque). If you use `unsafe` code, `fixed (int* addr = &(arr[0]))` will give you the address of the first int, and `addr + 1` (where addr + 1 is a C-like math operation on pointers) will be the address of the next element, like in C. (clearly the same is true for all the *value* types, `bool`, `int`, `DateTime`, and in general `struct`s) – xanatos Aug 11 '13 at 11:16
6

Yes, elements in a List are stored contiguously, just like an array. A List actually uses arrays internally, but that is an implementation detail that you shouldn't really need to be concerned with.

Of course, in order to get the correct impression from that statement, you also have to understand a bit about memory management in .NET. Namely, the difference between value types and reference types, and how objects of those types are stored. Value types will be stored in contiguous memory. With reference types, the references will be stored in contiguous memory, but not the instances themselves.

The advantage of using a List is that the logic inside of the class handles allocating and managing the items for you. You can add elements anywhere, remove elements from anywhere, and grow the entire size of the collection without having to do any extra work. This is, of course, also what makes a List slightly slower than an array. If any reallocation has to happen in order to comply with your request, there'll be a performance hit as a new, larger-sized array is allocated and the elements are copied to it. But it won't be any slower than if you wrote the code to do it manually with a raw array.

If your length requirement is fixed (i.e., you never need to grow/expand the total capacity of the array), you can go ahead and use a raw array. It might even be marginally faster than a List because it avoids the extra overhead and indirection (although that is subject to being optimized out by the JIT compiler).

If you need to be able to dynamically resize the collection, or you need any of the other features provided by the List class, just use a List. The performance difference will be virtually imperceptible.

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • :) Thanks, I get it. "the references will be stored in contiguous memory" is this means that when I have array consist of 100 element I have 100 reference in the stack refere to 100 instacnes in the heap? , I believed that it's only one reference store the location of first element and when i say arr[20] it use an equation based on the index(20), instace's size and the addrees of the first element to get the location of intended elemnet , forgive me i'm a new comer from C++ and dataStrucres but you are right i'll read about memory management in .NET :), sorry for my bad English. – Ramy Yousef Aug 11 '13 at 13:40
  • 1
    @Kasper Yes, references work much like pointers in C++. For reference types, you will basically have an array of pointers to objects stored on the heap. When you access item 20, the address of item 20 is retrieved. But in the .NET world, heap and stack are implementation details, so the terms are not often used because they have less precise meanings. – Cody Gray - on strike Aug 11 '13 at 13:43
  • @CodyGray Upvote for mentioning implementation details for heap vs stack. Eric would be proud. – davidcarr Sep 29 '20 at 14:18