Are List<> elements sequentially located in heap like array?

前端 未结 2 375
日久生厌
日久生厌 2021-01-06 06:46

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:

相关标签:
2条回答
  • 2021-01-06 07:13

    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.
    
    0 讨论(0)
  • 2021-01-06 07:13

    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.

    0 讨论(0)
提交回复
热议问题