我有一个IEnumerable<T>,我需要它的副本.任何实现的东西IEnumerable<T>都可以.什么是最便宜的复制方式?.ToArray()也许?
Meh*_*ari 22
ToArray不一定比快ToList.只是用ToList.
关键在于,在枚举之前你不知道原始序列的元素数量,你最终会调整一个数组的大小并像添加一样添加元素List<T>,所以无论如何ToArray都必须做同样的事情List<T>.此外,ToList给你一个List<T>比原始阵列更好的东西.
当然,如果你知道IEnumerable<T>实例的具体类型,可以有更快的方法,但这与关键点没有密切关系.
旁注:使用数组(除非必须)可以说是微优化,应该在大多数情况下避免 使用.
Enumerable::ToArray并Enumerable::ToList最终使用相同的技术从源接收元素到内部数组缓冲区,一旦达到该缓冲区的大小,它们将分配一个大小翻倍的新缓冲区,memcpy并继续添加元素,重复此过程直到枚举在源头上完成了.最后的差异在于ToArray,它在Buffer<T>内部使用实现,然后必须分配一个确切大小Array并在返回结果之前将元素复制到其中.另一方面,ToList只需要在其中返回List<T>带有潜在(可能)仅部分填充的数组缓冲区.
两种实现都有一个优化,如果源IEnumerable是一个,ICollection他们将实际分配正确的缓冲区大小开始使用ICollection::Count,然后ICollection::CopyTo从源使用来填充他们的缓冲区.
最后你会发现它们在大多数情况下几乎完全相同,但从List<T>技术上来说,它最后是一个"较重"的类,最后还有ToArray额外的分配+ memcpy(如果源不是ICollection)能够交回完全正确大小的阵列.我通常坚持ToList自己,除非我知道我需要将结果传递给需要数组的东西,比如说也许Task::WaitAll.