最简单的方法来复制IEnumerable <t>?</t>

时间:2010-12-31 04:38:42

标签: c#

我有一个IEnumerable<T>,我需要一份副本。任何实现IEnumerable<T>的东西都可以。什么是最便宜的复制方式?可能.ToArray()

5 个答案:

答案 0 :(得分:22)

ToArray不一定比ToList快。只需使用ToList

只要您在枚举之前不知道原始序列的元素数量,就会发现这一点,您最终会调整数组的大小并像List<T>一样向其添加元素,因此{{1无论如何,{} {}必须做同样的事情。此外,ToArray为您提供List<T>,这比原始数组更好。

当然,如果你知道ToList实例的具体类型,可以有更快的方法,但这与关键点没有密切关系。

旁注:使用数组(除非必须)可以说是微优化,应该是avoided most of the time

答案 1 :(得分:5)

Enumerable::ToArrayEnumerable::ToList最终使用相同的技术从源接收元素到内部数组缓冲区,一旦达到该缓冲区的大小,它们将分配一个大小的两倍的新缓冲区,memcpy结束并继续添加元素,重复此过程,直到源上的枚举完成。最后的差异是ToArray在内部使用Buffer<T>实现,然后必须分配一个确切大小的Array并在返回结果之前将元素复制到其中。另一方面,ToList只需返回List<T>内部可能(可能)仅部分填充的数组缓冲区。

两个实现都有一个优化,如果源IEnumerableICollection,他们将实际分配正确的缓冲区大小,以使用ICollection::Count开始,然后使用ICollection::CopyTo }从源头填充他们的缓冲区。

最后你会发现它们在大多数情况下的表现几乎相同,但List<T>在技术上是一个“较重”的类,最后要坚持,而ToArray有额外的分配+ memcpy在最后(如果源不是ICollection)能够交回完全正确大小的数组。我通常坚持使用ToList,除非我知道我需要将结果传递给需要数组的东西,比如说Task::WaitAll

答案 2 :(得分:4)

我准备建议使用.AsParallel().ToList()的可能性如果您有TPL可供使用,但我的双核笔记本电脑上的非正式测试显示它比仅仅.ToList()慢7倍。因此,请坚持使用Mehrdad's answer

答案 3 :(得分:2)

第二个最便宜的方式是说new List<T>(myEnumerable).ToArray()。最便宜的方法是使用.ToArray()(来自LINQ),或者,如果你没有C#3.5,创建你自己的缓冲区并在加倍的同时加上它的大小,然后在最后修剪它。

答案 4 :(得分:-1)

我知道这已经很老了......

为什么你不能做这样的事情......

的IEnumerable&LT; T&GT; original = {...在此处插入代码以填充...};

的IEnumerable&LT; T&GT; copy =(来自原始选择行中的行);

我之前使用过这个方法来推迟加载副本及其元素,直到我真正需要它们为止,而且,我不会更改“原始”的基础数据类型,将其转换为List类型。