我经常遇到我想在声明它的地方评估查询的情况。这通常是因为我需要多次迭代它 并且 计算成本很高。例如:
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()
然而,我想知道是否ToArray()是通过第一次调用实现的ToList(),因此内存效率低于调用ToList().
我疯了吗?我应该打电话ToArray()吗 - 知道内存不会被分配两次是安全的吗?
除非您只需要一个数组来满足您应该使用的其他约束ToList。在大多数情况下ToArray会分配比ToList.
ToList
ToArray
两者都使用数组进行存储,但ToList具有更灵活的约束。它需要数组至少与集合中元素的数量一样大。如果数组更大,那不是问题。但是ToArray,需要将数组的大小精确到元素的数量。
为了满足这个约束ToArray,通常比ToList. 一旦它有一个足够大的数组,它就会分配一个大小完全正确的数组并将元素复制回该数组。唯一可以避免这种情况的情况是,当数组的增长算法恰好与需要存储的元素数量一致时(绝对是少数)。
编辑
有几个人问我在List<T>值中有多余的未使用内存的后果。
List<T>
这是一个合理的担忧。如果创建的集合是长期存在的,在创建后从不修改,并且很有可能登陆 Gen2 堆,那么您最好预先分配额外的分配ToArray。
总的来说,尽管我发现这种情况很少见。更常见的是看到很多ToArray调用立即传递给其他短暂的内存使用,在这种情况下ToList显然更好。
这里的关键是分析,分析,然后再分析一些。