High memory consumption with Enumerable.Range?

前端 未结 4 639
轻奢々
轻奢々 2020-11-28 16:03

Originally i wanted to know whether ToList allocates more memory than using the constructor of List which takes an IEnumerable

4条回答
  •  天涯浪人
    2020-11-28 16:42

    This probably relates to the doubling algorithm used to resize the backing buffer when adding to a list. When you allocate as an array, the length of that is known, and can be queried by checking for IList[] and/or ICollection[]; thus it can allocate a single array, right-sized the first time, and then just block-copy the contents.

    With the sequence this is not possible (the sequence does not expose the length in any accessible way); thus it must instead fall back to "keep filling up the buffer; if full, double it and copy".

    Obviously this needs approx double the memory.

    An interesting test would be:

    var list = new List(10000000);
    list.AddRange(Enumerable.Range(1, 10000000));
    

    This will allocate the right size initially, while still using the sequence.

    tl;dr; the constructor, when passed a sequence, first checks to see if it can obtain the length by casting to a well-known interface.

提交回复
热议问题