我经常遇到这样的情况:我想在声明查询的地方对查询进行求值。这通常是因为我需要对它进行多次迭代,计算成本很高。例如:
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() -在知道内存不会被分配两次的情况下安全可靠?
我同意@mquander的观点,性能差异应该是微不足道的。但是,我想对它进行基准测试,所以我这样做了——结果是微不足道的。
Testing with List<T> source:
ToArray time: 1934 ms (0.01934 ms/call), memory used: 4021 bytes/array
ToList time: 1902 ms (0.01902 ms/call), memory used: 4045 bytes/List
Testing with array source:
ToArray time: 1957 ms (0.01957 ms/call), memory used: 4021 bytes/array
ToList time: 2022 ms (0.02022 ms/call), memory used: 4045 bytes/List
每个源数组/列表有1000个元素。所以你可以看到时间和记忆的差异都可以忽略不计。
我的结论是:您还可以使用ToList(),因为List<T>提供了比数组更多的功能,除非几个字节的内存确实对您很重要。
首选ToListAsync<T>()。
在实体框架6中,这两个方法最终都调用相同的内部方法,但ToArrayAsync<T>()在最后调用list.ToArray(),实现为
T[] array = new T[_size];
Array.Copy(_items, 0, array, 0, _size);
return array;
所以ToArrayAsync<T>()有一些开销,因此ToListAsync<T>()是首选。