I've got an IEnumerable<T>
, and I need a copy of it. Anything that implements IEnumerable<T>
will do just fine. What's the cheapest way to copy it? .ToArray()
maybe?

- 272,448
- 266
- 850
- 1,236
-
@JimBalter Single-dimensional arrays _do_ implement IEnumerable
. They also implement IList – relatively_random May 11 '21 at 15:23.
4 Answers
ToArray
is not necessarily faster than ToList
. Just use ToList
.
The point is as long as you don't know the number of elements of the original sequence before enumerating, you end up with resizing an array and adding elements to it like a List<T>
does, so ToArray
will have to do the same thing a List<T>
does anyway. Besides, ToList
gives you a List<T>
and that's nicer than a raw array.
Of course, if you know the concrete type of the IEnumerable<T>
instance, there can be faster methods, but that's not germane to the point.
Side note: using an array (unless you have to) is arguably a micro-optimization and should be avoided most of the time.

- 1
- 1

- 414,610
- 91
- 852
- 789
-
-
1+1. In fact, Mono's [`Enumerable.ToArray`](https://github.com/mono/mono/blob/master/mcs/class/System.Core/System.Linq/Enumerable.cs#L2794) uses `new List
(source).ToArray ()`, unless the `IEnumerable – Matthew Flaschen Dec 31 '10 at 04:59` happens to be a `ICollection `. I would not be surprised if MS's was similar. -
1How "micro"? I might want to use this in my NP-complete algorithm... every optimization helps (it's horrendously slow). – mpen Dec 31 '10 at 05:52
-
4I know this is an old post, but I'd like to point out that using a `List<>` instead of an array is if anything an even worse "microoptimization". To wit: Array's are nasty due to mutability issues; but `List`s are even worse - even the size is mutable. They're possibly very slightly faster in construction but slower in the much more common read-heavy usage; and `List<>` has more GC pressure. So if anything, by default both for conservative program correctness and perfomance, the default choice should be array over `List<>`. – Eamon Nerbonne Jul 23 '12 at 23:25
-
1^ Access to List elements may or may not be slower, depending on the JIT. As for the rest ... List's Count is just a getter that returns the array size. If an array will do, then the List's Count won't change so it's effectively immutable nor is there any "GC pressure". A List is just an array and a capacity (there's the small amount of extra memory) plus some code. Code that isn't executed doesn't have any consequences. Eamon's comment is particularly odd because it's entirely about micro-optimization. But then, he is correct ... ToArray is logically correct here; ToList is not. – Jim Balter Nov 28 '18 at 04:07
Enumerable::ToArray
and Enumerable::ToList
ultimately use the same technique to receive elements from the source into an internal array buffer and, once the size of that buffer is reached, they will allocate a new buffer double the size, memcpy over and continue adding elements, repeating this process until enumeration over the source is complete. The difference in the end is that ToArray
, which uses a Buffer<T>
implementation internally, must then allocate an exactly sized Array
and copy the elements into it before returning the result. On the other hand, ToList
just needs to return the List<T>
with a potentially (likely) only partially filled array buffer inside of it.
Both implementations also have an optimization where if the source IEnumerable
is an ICollection
they will actually allocate the exact right buffer size to begin with using ICollection::Count
and then use ICollection::CopyTo
from the source to fill their buffers.
In the end you will find that they perform nearly identically in most situations, but the List<T>
is technically a "heavier" class to hang on to in the end and the ToArray
has that extra allocate + memcpy at the end (if the source isn't an ICollection
) to be able to hand back the exactly right sized array. I usually stick with ToList
myself unless I know I need to pass the result to something that requires an array like say maybe Task::WaitAll
.

- 33,111
- 3
- 82
- 100
I was about to suggest the possibility of using .AsParallel().ToList()
if you have TPL at your disposal, but informal testing on my dual-core laptop shows it to be 7x slower than just .ToList()
. So, stick with Mehrdad's answer.

- 1
- 1

- 19,901
- 3
- 68
- 87
-
1+1 That's potentially a good alternative, and depending on the nature of the receiver object, it can be a lot faster, but that falls into "not germane to the point" category. – Mehrdad Afshari Dec 31 '10 at 06:07
The second-to-cheapest way is to say new List<T>(myEnumerable).ToArray()
. The cheapest way is to use either .ToArray()
(from LINQ) or, if you don't have C# 3.5, to create your own buffer and add to it while doubling its size, then trim it at the end.

- 205,094
- 128
- 528
- 886
-
1Since the OP just wants a collection of any sort, it's pointlessly inefficient to create a list and then create an array from it ... just do `new List
(myEnumerable)` (which, BTW, is cheaper than `Enumerable.ToArray – Jim Balter Nov 28 '18 at 04:12`).