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[<T>]
and/or ICollection[<T>]
; 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<int>(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.