在LINQ查询中,是调用ToList()还是ToArray()更好?
在LINQ查询中,是调用ToList()还是ToArray()更好?
我经常遇到这样的情况:我想在声明查询时立即评估它。这通常是因为我需要多次迭代它而且计算代价昂贵。例如:
string raw = "..."; var lines = (from l in raw.Split('\n') let ll = l.Trim() where !string.IsNullOrEmpty(ll) select ll).ToList();
这很好用。但如果我不打算修改结果,那我可能可以直接调用 ToArray()
而不是 ToList()
。
我想知道 ToArray()
是否是通过首先调用 ToList()
实现的,因此比直接调用 ToList()
的内存效率更低。
我疯了吗?我应该只调用 ToArray()
吗,放心,知道内存不会分配两次吗?
admin 更改状态以发布 2023年5月20日
除非你只是需要一个数组来满足其他约束条件,否则你应该使用ToList
。在大多数情况下,ToArray
比ToList
分配更多的内存。
两者都使用数组进行存储,但ToList
具有更灵活的限制。它需要数组至少与集合中的元素数量一样大。如果数组更大,那没问题。然而,ToArray
需要数组的大小正好等于元素的数量。
为了满足这个限制,ToArray
通常比ToList
多分配一个数组。一旦它有一个足够大的数组,它就会分配一个大小完全正确的数组,并将元素复制回该数组。它能够避免这种情况的唯一时间是当数组的增长算法恰好与需要存储的元素数量重合时(绝对是少数情况)。
编辑
有几个人问我在List
值中有额外未使用的内存的后果。
这是一个有效的担忧。如果创建的集合具有长生命周期,在创建后从未被修改,并且在Gen2堆中具有很高的概率,则最好在一开始就将ToArray
的额外分配作为开销。
总的来说,我认为这是较少见的情况。更常见的是看到许多ToArray
调用,它们立即传递给其他短期内存使用,在这种情况下,ToList
显然更好。
关键在于进行性能分析,性能分析以及更多性能分析。