Is it better to call ToList() or ToArray() in LINQ queries?
我经常遇到这样的情况:我想在声明查询的地方对其进行eval。这通常是因为我需要多次迭代它,并且计算起来很昂贵。例如:
1 2 3 4 5 6 | string raw ="..."; var lines = (from l in raw.Split(' ') let ll = l.Trim() where !string.IsNullOrEmpty(ll) select ll).ToList(); |
这个很好用。但是如果我不想修改结果,那么我可以调用
不过,我想知道
我疯了吗?我应该打电话给
除非您只需要一个数组来满足其他约束,否则应该使用
两者都使用阵列进行存储,但
为了满足这个限制,
编辑
有几个人问过我,在
这是一个值得关注的问题。如果创建的集合寿命长,在创建后从不进行修改,并且有很高的机会登录到gen2堆中,那么您最好预先获得
总的来说,虽然我发现这是一个更罕见的情况。很多
这里的关键是分析,分析,然后分析更多。
由于
如果您希望对这一事实进行具体的确认,请查看Reflector中所讨论方法的实现——您将看到它们归结为几乎相同的代码。
(七年后……)
其他一些(好的)答案集中在微观性能的差异上。
本文只是对数组(
最好举例说明:
1 2 3 4 5 6 7 8 | IList<int> source = Enumerable.Range(1, 10).ToArray(); // try changing to .ToList() foreach (var x in source) { if (x == 5) source[8] *= 100; Console.WriteLine(x); } |
上述代码将毫无例外地运行并生成输出:
1 2 3 4 5 6 7 8 9 10 | 1 2 3 4 5 6 7 8 900 10 |
这表明,由
注意,我把局部变量
现在,如果我把
1 2 3 4 5 | 1 2 3 4 5 |
接着是一个
Collection was modified; enumeration operation may not execute.
在这种情况下,底层枚举器是公共可变值类型
综上所述,
人们经常添加一个额外的
(如果有人想知道
我同意@mquander的观点,即性能差异应该是微不足道的。然而,我想确定它的基准,所以我做了——这是微不足道的。
1 2 3 4 5 6 7 | 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(),因为
如果您在
内存总是会被分配两次,或者接近这个分配。由于不能调整数组的大小,这两种方法都将使用某种机制来收集不断增长的集合中的数据。(好吧,这个列表本身就是一个不断增长的集合。)
该列表使用一个数组作为内部存储,并在需要时将容量加倍。这意味着平均2/3的项目至少被重新分配一次,一半的项目至少被重新分配两次,一半的项目至少被重新分配三次,依此类推。这意味着每个项目平均被重新分配了1.3次,这不是很大的开销。
还请记住,如果要收集字符串,集合本身只包含对字符串的引用,则不会重新分配字符串本身。
编辑:此答案的最后部分无效。但是,其余的信息仍然是有用的,所以我会留下来。
我知道这是一篇老文章,但在有了同样的问题并做了一些研究之后,我发现了一些有趣的东西,也许值得分享。
首先,我同意@mquander及其答案。他说的是正确的,在表演方面,两者是相同的。
不过,我一直在使用Reflector来查看
有趣的是,微软选择只优化
回答得很晚,但我认为这对谷歌有帮助。
当他们使用LINQ创建时都很糟糕。它们都实现了相同的代码,以便在必要时调整缓冲区的大小。
ToList做了同样的事情,但是它跳过了最后的分配,因为您可以在将来添加项目。列表不关心它是从LINQ查询创建的还是手动创建的。
对于创建列表,内存更好,CPU更差,因为列表是一个通用的解决方案,每个操作都需要在.NET内部数组范围检查之外进行范围检查。
因此,如果您将在结果集中迭代太多次,那么数组是好的,因为它意味着范围检查比列表少,编译器通常会为顺序访问优化数组。
如果在创建列表时指定容量参数,则该列表的初始化分配会更好。在这种情况下,它只分配一次数组,假设您知道结果的大小。linq的
为了完成这个答案,我必须写以下句子
您应该根据理想的设计选择来决定选择
如果性能很重要,您还应该考虑什么操作更快。实际上,你不会给
不久前在我自己的测试中,我发现
我发现人们在这里所做的其他基准都是不足的,所以这就是我在这方面所做的努力。如果你发现我的方法有问题,请告诉我。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | /* This is a benchmarking template I use in LINQPad when I want to do a * quick performance test. Just give it a couple of actions to test and * it will give you a pretty good idea of how long they take compared * to one another. It's not perfect: You can expect a 3% error margin * under ideal circumstances. But if you're not going to improve * performance by more than 3%, you probably don't care anyway.*/ void Main() { // Enter setup code here var values = Enumerable.Range(1, 100000) .Select(i => i.ToString()) .ToArray() .Select(i => i); values.GetType().Dump(); var actions = new[] { new TimedAction("ToList", () => { values.ToList(); }), new TimedAction("ToArray", () => { values.ToArray(); }), new TimedAction("Control", () => { foreach (var element in values) { // do nothing } }), // Add tests as desired }; const int TimesToRun = 1000; // Tweak this as necessary TimeActions(TimesToRun, actions); } #region timer helper methods // Define other methods and classes here public void TimeActions(int iterations, params TimedAction[] actions) { Stopwatch s = new Stopwatch(); int length = actions.Length; var results = new ActionResult[actions.Length]; // Perform the actions in their initial order. for (int i = 0; i < length; i++) { var action = actions[i]; var result = results[i] = new ActionResult { Message = action.Message }; // Do a dry run to get things ramped up/cached result.DryRun1 = s.Time(action.Action, 10); result.FullRun1 = s.Time(action.Action, iterations); } // Perform the actions in reverse order. for (int i = length - 1; i >= 0; i--) { var action = actions[i]; var result = results[i]; // Do a dry run to get things ramped up/cached result.DryRun2 = s.Time(action.Action, 10); result.FullRun2 = s.Time(action.Action, iterations); } results.Dump(); } public class ActionResult { public string Message { get; set; } public double DryRun1 { get; set; } public double DryRun2 { get; set; } public double FullRun1 { get; set; } public double FullRun2 { get; set; } } public class TimedAction { public TimedAction(string message, Action action) { Message = message; Action = action; } public string Message { get; private set; } public Action Action { get; private set; } } public static class StopwatchExtensions { public static double Time(this Stopwatch sw, Action action, int iterations) { sw.Restart(); for (int i = 0; i < iterations; i++) { action(); } sw.Stop(); return sw.Elapsed.TotalMilliseconds; } } #endregion |
您可以在这里下载linqpad脚本。
结果:
调整上面的代码,您会发现:
这与最高投票答案的结论一致:
更新
@Jonhanna指出,根据
这是一个古老的问题——但是为了让偶然发现它的用户受益,还有一个"memoizing"可枚举的替代方法——它可以缓存和停止一个Linq语句的多个枚举,这就是ToArray()和ToList()经常使用的方法,即使列表或数组的集合属性是NeveR使用。
memoize可在rx/system.interactive lib中找到,并在此处解释:更多LINQ与System.Interactive
(摘自Bart de'smet的博客,如果你经常和Linq to Objects打交道,这是一篇强烈推荐的文章)
一个选项是添加您自己的扩展方法,该方法返回只读
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public static class EnumerableExtension { /// <summary> /// Causes immediate evaluation of the linq but only if required. /// As it returns a readonly ICollection, is better than using ToList or ToArray /// when you do not want to use the indexing properties of an IList, or add to the collection. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="enumerable"></param> /// <returns>Readonly collection</returns> public static ICollection<T> Evaluate<T>(this IEnumerable<T> enumerable) { //if it's already a readonly collection, use it var collection = enumerable as ICollection<T>; if ((collection != null) && collection.IsReadOnly) { return collection; } //or make a new collection return enumerable.ToList().AsReadOnly(); } } |
单元测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | [TestClass] public sealed class EvaluateLinqTests { [TestMethod] public void EvalTest() { var list = new List<int> {1, 2, 3}; var linqResult = list.Select(i => i); var linqResultEvaluated = list.Select(i => i).Evaluate(); list.Clear(); Assert.AreEqual(0, linqResult.Count()); //even though we have cleared the underlying list, the evaluated list does not change Assert.AreEqual(3, linqResultEvaluated.Count()); } [TestMethod] public void DoesNotSaveCreatingListWhenHasListTest() { var list = new List<int> {1, 2, 3}; var linqResultEvaluated = list.Evaluate(); //list is not readonly, so we expect a new list Assert.AreNotSame(list, linqResultEvaluated); } [TestMethod] public void SavesCreatingListWhenHasReadonlyListTest() { var list = new List<int> {1, 2, 3}.AsReadOnly(); var linqResultEvaluated = list.Evaluate(); //list is readonly, so we don't expect a new list Assert.AreSame(list, linqResultEvaluated); } [TestMethod] public void SavesCreatingListWhenHasArrayTest() { var list = new[] {1, 2, 3}; var linqResultEvaluated = list.Evaluate(); //arrays are readonly (wrt ICollection<T> interface), so we don't expect a new object Assert.AreSame(list, linqResultEvaluated); } [TestMethod] [ExpectedException(typeof (NotSupportedException))] public void CantAddToResultTest() { var list = new List<int> {1, 2, 3}; var linqResultEvaluated = list.Evaluate(); Assert.AreNotSame(list, linqResultEvaluated); linqResultEvaluated.Add(4); } [TestMethod] [ExpectedException(typeof (NotSupportedException))] public void CantRemoveFromResultTest() { var list = new List<int> {1, 2, 3}; var linqResultEvaluated = list.Evaluate(); Assert.AreNotSame(list, linqResultEvaluated); linqResultEvaluated.Remove(1); } } |
老问题,新问题的人。
根据system.linq.enumerable的来源,
About memory allocation:
在只运行
About the runtime efficient:
那些质疑这个问题的人可以在你自己的机器上运行以下代码,你就会得到答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | class PersonC { public Guid uuid; public string name; public int age; public bool sex; public DateTime BirthDay; public double weight; } struct PersonS { public Guid uuid; public string name; public int age; public bool sex; public DateTime BirthDay; public double weight; } class PersonT<T> : IEnumerable<T> { private List<T> items; public PersonT(IEnumerable<T> init) { items = new List<T>(init); } public IEnumerator<T> GetEnumerator() => items.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator(); } private IEnumerable<PersonC> C(int count) { for (var i = 0; i < count; ++i) { var guid = Guid.NewGuid(); var guidBytes = guid.ToByteArray(); //16 bytes yield return new PersonC { uuid = guid, name = guid.ToString(), age = guidBytes[0] ^ guidBytes[7], sex = guidBytes[14] % 2 == 0, BirthDay = DateTime.Now.AddDays(-guidBytes[11] * 18), weight = guidBytes[12] * 100 }; } } private IEnumerable<PersonS> S(int count) { for (var i = 0; i < count; ++i) { var guid = Guid.NewGuid(); var guidBytes = guid.ToByteArray(); //16 bytes yield return new PersonS { uuid = guid, name = guid.ToString(), age = guidBytes[0] ^ guidBytes[7], sex = guidBytes[14] % 2 == 0, BirthDay = DateTime.Now.AddDays(-guidBytes[11] * 18), weight = guidBytes[12] * 100 }; } } private void MakeLog(string test, List<long> log) => Console.WriteLine("{0} {1} ms -> [{2}]", test, log.Average(), string.Join(",", log) ); private void Test1(int times, int count) { var test = Enumerable.Range(1, times).ToArray(); MakeLog("C.ToList", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = C(count).ToList(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); MakeLog("C.ToArray", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = C(count).ToArray(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); MakeLog("S.ToList", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = S(count).ToList(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); MakeLog("S.ToArray", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = S(count).ToArray(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); } private void Test2(int times, int count) { var test = Enumerable.Range(1, times).ToArray(); var dataC1 = new PersonT<PersonC>(C(count)); var dataS1 = new PersonT<PersonS>(S(count)); MakeLog("C1.ToList", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = dataC1.ToList(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); MakeLog("C1.ToArray", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = dataC1.ToArray(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); MakeLog("S1.ToList", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = dataS1.ToList(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); MakeLog("S1.ToArray", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = dataS1.ToArray(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); } private void Test3(int times, int count) { var test = Enumerable.Range(1, times).ToArray(); var dataC2 = (ICollection<PersonC>) new List<PersonC>(C(count)); var dataS2 = (ICollection<PersonS>) new List<PersonS>(S(count)); MakeLog("C2.ToList", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = dataC2.ToList(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); MakeLog("C2.ToArray", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = dataC2.ToArray(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); MakeLog("S2.ToList", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = dataS2.ToList(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); MakeLog("S2.ToArray", test.Select(o => { var sw = new Stopwatch(); GC.Collect(); sw.Start(); var ret = dataS2.ToArray(); sw.Stop(); return sw.ElapsedMilliseconds; }).ToList()); } private void TestMain() { const int times = 100; const int count = 1_000_000 + 1; Test1(times, count); Test2(times, count); Test3(times, count); } |
我在我的机器上得到了这些结果:
Group1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | C.ToList 761.79 ms -> [775, 755, 759, 759, 756, 759, 765, 750, 757, 762, 759, 754, 757, 753, 763, 753, 759, 756, 768, 754, 763, 757, 757, 777, 780, 758, 754, 758, 762, 754, 758, 757, 763, 758, 760, 754, 761, 755, 764, 847, 952, 755, 747, 763, 760, 758, 754, 763, 761, 758, 750, 764, 757, 763, 762, 756, 753, 759, 759, 757, 758, 779, 765, 760, 760, 756, 760, 756, 755, 764, 759, 753, 757, 760, 752, 764, 758, 760, 758, 760, 755, 761, 751, 753, 761, 762, 761, 758, 759, 752, 765, 756, 760, 755, 757, 753, 760, 751, 755, 779] C.ToArray 782.56 ms -> [783, 774, 771, 771, 773, 774, 775, 775, 772, 770, 771, 774, 771, 1023, 975, 772, 767, 776, 771, 779, 772, 779, 775, 771, 775, 773, 775, 771, 765, 774, 770, 781, 772, 771, 781, 762, 817, 770, 775, 779, 769, 774, 763, 775, 777, 769, 777, 772, 775, 778, 775, 771, 770, 774, 772, 769, 772, 769, 774, 775, 768, 775, 769, 774, 771, 776, 774, 773, 778, 769, 778, 767, 770, 787, 783, 779, 771, 768, 805, 780, 779, 767, 773, 771, 773, 785, 1044, 853, 775, 774, 775, 771, 770, 769, 770, 776, 770, 780, 821, 770] S.ToList 704.2 ms -> [687, 702, 709, 691, 694, 710, 696, 698, 700, 694, 701, 719, 706, 694, 702, 699, 699, 703, 704, 701, 703, 705, 697, 707, 691, 697, 707, 692, 721, 698, 695, 700, 704, 700, 701, 710, 700, 705, 697, 711, 694, 700, 695, 698, 701, 692, 696, 702, 690, 699, 708, 700, 703, 714, 701, 697, 700, 699, 694, 701, 697, 696, 699, 694, 709, 1068, 690, 706, 699, 699, 695, 708, 695, 704, 704, 700, 695, 704, 695, 696, 702, 700, 710, 708, 693, 697, 702, 694, 700, 706, 699, 695, 706, 714, 704, 700, 695, 697, 707, 704] S.ToArray 742.5 ms -> [742, 743, 733, 745, 741, 724, 738, 745, 728, 732, 740, 727, 739, 740, 726, 744, 758, 732, 744, 745, 730, 739, 738, 723, 745, 757, 729, 741, 736, 724, 744, 756, 739, 766, 737, 725, 741, 742, 736, 748, 742, 721, 746, 1043, 806, 747, 731, 727, 742, 742, 726, 738, 746, 727, 739, 743, 730, 744, 753, 741, 739, 746, 728, 740, 744, 734, 734, 738, 731, 747, 736, 731, 765, 735, 726, 740, 743, 730, 746, 742, 725, 731, 757, 734, 738, 741, 732, 747, 744, 721, 742, 741, 727, 745, 740, 730, 747, 760, 737, 740] C1.ToList 32.34 ms -> [35, 31, 31, 31, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 33, 32, 31, 31, 31, 31, 30, 32, 31, 31, 31, 31, 32, 30, 31, 31, 31, 30, 32, 31, 31, 31, 36, 31, 31, 31, 32, 30, 31, 32, 31, 31, 31, 31, 31, 32, 31, 31, 31, 31, 33, 32, 31, 32, 31, 31, 33, 31, 31, 31, 31, 31, 32, 31, 32, 31, 34, 38, 68, 42, 79, 33, 31, 31, 31, 31, 31, 30, 30, 30, 30, 31, 31, 31, 31, 32, 31, 32, 31, 31, 31, 32, 33, 33, 31, 31] C1.ToArray 56.32 ms -> [57, 56, 59, 54, 54, 55, 56, 57, 54, 54, 55, 55, 57, 56, 59, 57, 56, 58, 56, 56, 54, 56, 57, 55, 55, 55, 57, 58, 57, 58, 55, 55, 56, 55, 57, 56, 56, 59, 56, 56, 56, 56, 58, 56, 57, 56, 56, 57, 56, 55, 56, 56, 56, 59, 56, 56, 56, 55, 55, 54, 55, 54, 57, 56, 56, 56, 55, 55, 56, 56, 56, 59, 56, 56, 57, 56, 57, 56, 56, 56, 56, 62, 55, 56, 56, 56, 69, 57, 58, 56, 57, 58, 56, 57, 56, 56, 56, 56, 56, 56] S1.ToList 88.69 ms -> [96, 90, 90, 89, 91, 88, 89, 90, 96, 89, 89, 89, 90, 90, 90, 89, 90, 90, 89, 90, 89, 91, 89, 91, 89, 91, 89, 90, 90, 89, 87, 88, 87, 88, 87, 87, 87, 87, 88, 88, 87, 87, 89, 87, 87, 87, 91, 88, 87, 86, 89, 87, 90, 89, 89, 90, 89, 87, 87, 87, 86, 87, 88, 90, 88, 87, 87, 92, 87, 87, 88, 88, 88, 86, 86, 87, 88, 87, 87, 87, 89, 87, 89, 87, 90, 89, 89, 89, 91, 89, 90, 89, 90, 88, 90, 90, 90, 88, 89, 89] S1.ToArray 143.26 ms -> [130, 129, 130, 131, 133, 130, 131, 130, 135, 137, 130, 136, 132, 131, 130, 131, 132, 130, 132, 136, 130, 131, 157, 153, 194, 364, 176, 189, 203, 194, 189, 192, 183, 140, 142, 147, 145, 134, 159, 158, 142, 167, 130, 143, 145, 144, 160, 154, 156, 153, 153, 164, 142, 145, 137, 134, 145, 143, 142, 135, 133, 133, 135, 134, 134, 139, 139, 133, 134, 141, 133, 132, 133, 132, 133, 131, 135, 132, 133, 132, 128, 128, 130, 132, 129, 129, 129, 129, 129, 128, 134, 129, 129, 129, 129, 128, 128, 137, 130, 131] C2.ToList 3.25 ms -> [5, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3] C2.ToArray 3.37 ms -> [4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 4, 9, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 4, 4, 3, 4, 4, 3, 3, 4, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 4, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3] S2.ToList 37.72 ms -> [38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 40, 38, 38, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 39, 37, 37, 39, 38, 37, 37, 37, 37, 39, 38, 37, 37, 38, 37, 38, 37, 37, 38, 37, 37, 37, 38, 37, 37, 36, 37, 38, 37, 39, 37, 39, 38, 37, 38, 38, 38, 38, 38, 38, 37, 38, 38, 38, 38, 38, 37, 38, 37, 37, 38, 37, 37, 39, 41, 37, 38, 38, 37, 37, 37, 37, 38, 37, 37, 37, 40, 37, 37, 37, 37, 39, 38] S2.ToArray 38.86 ms -> [39, 37, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 38, 38, 38, 39, 37, 38, 38, 38, 38, 38, 37, 37, 38, 37, 37, 38, 38, 40, 38, 38, 38, 38, 38, 39, 38, 38, 39, 38, 38, 39, 38, 38, 40, 38, 39, 38, 38, 39, 38, 38, 38, 38, 38, 39, 38, 38, 38, 39, 39, 37, 38, 38, 39, 71, 78, 37, 37, 37, 39, 38, 38, 39, 38, 38, 38, 38, 38, 39, 38, 38, 38, 39, 38, 38, 38] |
Group2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | C.ToList 756.81 ms C.ToArray 774.21 ms S.ToList 709.7 ms S.ToArray 753.51 ms C1.ToList 32.06 ms C1.ToArray 56.58 ms S1.ToList 89.43 ms S1.ToArray 132.85 ms C2.ToList 3.45 ms C2.ToArray 3.36 ms S2.ToList 41.43 ms S2.ToArray 40.84 ms |
Group3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | C.ToList 756.64 ms C.ToArray 771.56 ms S.ToList 705.42 ms S.ToArray 749.59 ms C1.ToList 31.45 ms C1.ToArray 57.03 ms S1.ToList 91.26 ms S1.ToArray 129.77 ms C2.ToList 3.26 ms C2.ToArray 3.29 ms S2.ToList 41.57 ms S2.ToArray 40.69 ms |
Group4:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | C.ToList 729.65 ms -> [749, 730, 721, 719, 723, 743, 721, 724, 727, 722, 716, 725, 723, 726, 718, 722, 731, 722, 723, 725, 723, 722, 728, 726, 728, 718, 726, 1088, 788, 737, 729, 710, 730, 728, 717, 723, 728, 721, 722, 728, 722, 736, 723, 729, 732, 724, 726, 727, 728, 728, 726, 726, 725, 727, 725, 728, 728, 718, 724, 725, 726, 724, 726, 729, 727, 722, 722, 725, 725, 728, 724, 727, 738, 717, 726, 723, 725, 725, 727, 724, 720, 726, 726, 723, 727, 730, 723, 721, 725, 727, 727, 733, 720, 722, 722, 725, 722, 725, 728, 726] C.ToArray 788.36 ms -> [748, 740, 742, 797, 1090, 774, 781, 787, 784, 786, 786, 782, 781, 781, 784, 783, 783, 781, 783, 787, 783, 784, 775, 789, 784, 785, 778, 774, 781, 783, 786, 781, 780, 788, 778, 785, 777, 781, 786, 782, 781, 787, 782, 787, 784, 773, 783, 782, 781, 777, 783, 781, 785, 788, 777, 776, 784, 784, 783, 789, 778, 781, 791, 768, 779, 783, 781, 787, 786, 781, 784, 781, 785, 781, 780, 809, 1155, 780, 790, 789, 783, 776, 785, 783, 786, 787, 782, 782, 787, 777, 779, 784, 783, 776, 786, 775, 782, 779, 784, 784] S.ToList 705.54 ms -> [690, 705, 709, 708, 702, 707, 703, 696, 703, 702, 700, 703, 700, 707, 705, 699, 697, 703, 695, 698, 707, 697, 711, 710, 699, 700, 708, 707, 693, 710, 704, 691, 702, 700, 703, 700, 705, 700, 703, 695, 709, 705, 698, 699, 709, 700, 699, 704, 691, 705, 703, 700, 708, 1048, 710, 706, 706, 692, 702, 705, 695, 701, 710, 697, 698, 706, 705, 707, 707, 695, 698, 704, 698, 699, 705, 698, 703, 702, 701, 697, 702, 702, 704, 703, 699, 707, 703, 705, 701, 717, 698, 695, 713, 696, 708, 705, 697, 699, 700, 698] S.ToArray 745.01 ms -> [751, 743, 727, 734, 736, 745, 739, 750, 739, 750, 758, 739, 744, 738, 730, 744, 745, 739, 744, 750, 733, 735, 743, 731, 749, 748, 727, 746, 749, 731, 737, 803, 1059, 756, 769, 748, 740, 745, 741, 746, 749, 732, 741, 742, 732, 744, 746, 737, 742, 739, 733, 744, 741, 729, 746, 760, 725, 741, 764, 739, 750, 751, 727, 745, 738, 727, 735, 741, 720, 736, 740, 733, 741, 746, 731, 749, 756, 740, 738, 736, 732, 741, 741, 733, 741, 744, 736, 742, 742, 735, 743, 746, 729, 748, 765, 743, 734, 742, 728, 749] C1.ToList 32.27 ms -> [36, 31, 31, 32, 31, 32, 31, 30, 32, 30, 30, 30, 34, 32, 31, 31, 31, 31, 31, 31, 31, 32, 38, 51, 68, 57, 35, 30, 31, 31, 30, 30, 33, 30, 31, 34, 31, 34, 32, 31, 31, 31, 31, 32, 30, 30, 31, 30, 31, 31, 32, 31, 31, 31, 32, 31, 31, 31, 32, 31, 33, 31, 31, 32, 30, 30, 30, 30, 30, 33, 30, 33, 32, 31, 30, 31, 31, 32, 32, 31, 35, 31, 34, 31, 31, 32, 31, 31, 32, 31, 32, 31, 31, 35, 31, 31, 31, 31, 31, 32] C1.ToArray 56.72 ms -> [58, 56, 57, 57, 59, 58, 58, 57, 56, 59, 57, 55, 55, 54, 56, 55, 56, 56, 57, 59, 56, 55, 58, 56, 55, 55, 55, 55, 58, 58, 55, 57, 57, 56, 57, 57, 57, 57, 59, 59, 56, 57, 56, 57, 57, 56, 57, 59, 58, 56, 57, 57, 57, 58, 56, 56, 59, 56, 59, 57, 57, 57, 57, 59, 57, 56, 57, 56, 58, 56, 57, 56, 57, 59, 55, 58, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 56, 56, 57, 56, 56, 57, 58, 57, 57, 57, 57, 57] S1.ToList 90.72 ms -> [95, 90, 90, 89, 89, 89, 91, 89, 89, 87, 91, 89, 89, 89, 91, 89, 89, 89, 90, 89, 89, 90, 88, 89, 88, 90, 89, 90, 89, 89, 90, 90, 89, 89, 90, 91, 89, 91, 89, 90, 89, 89, 90, 91, 89, 89, 89, 89, 89, 89, 90, 89, 89, 89, 90, 89, 90, 89, 91, 89, 90, 89, 90, 89, 90, 89, 96, 89, 90, 89, 89, 89, 89, 89, 90, 89, 89, 89, 90, 87, 89, 90, 90, 91, 89, 91, 89, 89, 90, 91, 90, 89, 93, 144, 149, 90, 90, 89, 89, 89] S1.ToArray 131.4 ms -> [130, 128, 127, 134, 129, 129, 130, 136, 131, 130, 132, 132, 133, 131, 132, 131, 133, 132, 130, 131, 132, 131, 130, 133, 133, 130, 130, 131, 131, 131, 132, 134, 131, 131, 132, 131, 132, 131, 134, 131, 131, 130, 131, 131, 130, 132, 129, 131, 131, 131, 132, 131, 133, 134, 131, 131, 132, 132, 131, 133, 131, 131, 130, 133, 131, 130, 134, 132, 131, 132, 132, 131, 131, 134, 131, 131, 132, 132, 131, 130, 138, 130, 130, 131, 132, 132, 130, 134, 131, 131, 132, 131, 130, 132, 133, 131, 131, 131, 130, 131] C2.ToList 3.21 ms -> [4, 3, 3, 3, 4, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3] C2.ToArray 3.22 ms -> [4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 3, 4] S2.ToList 41.46 ms -> [42, 40, 41, 40, 42, 40, 40, 40, 40, 40, 40, 40, 40, 41, 40, 40, 41, 40, 40, 40, 39, 41, 41, 39, 40, 40, 43, 40, 39, 40, 40, 40, 40, 40, 40, 41, 40, 40, 40, 43, 40, 43, 75, 76, 47, 39, 40, 40, 40, 40, 42, 40, 41, 40, 40, 40, 44, 41, 40, 42, 42, 40, 41, 41, 41, 41, 41, 40, 41, 41, 41, 41, 42, 41, 40, 41, 41, 42, 42, 41, 40, 41, 41, 41, 41, 41, 40, 42, 40, 42, 41, 41, 41, 43, 41, 41, 41, 41, 42, 41] S2.ToArray 41.14 ms -> [42, 41, 41, 40, 40, 40, 40, 41, 41, 42, 41, 42, 41, 41, 41, 42, 41, 41, 42, 41, 41, 41, 41, 41, 42, 40, 41, 40, 42, 40, 42, 41, 40, 42, 41, 41, 43, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 41, 41, 41, 40, 42, 41, 41, 41, 41, 41, 40, 41, 41, 42, 41, 41, 41, 42, 41, 41, 41, 41, 41, 41, 42, 42, 42, 41, 45, 46, 41, 40, 41, 41, 42, 41, 41, 41, 41, 41, 41, 40, 41, 43, 40, 40, 40, 40, 43, 41] |
Group5:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | C.ToList 757.06 ms -> [770, 752, 752, 751, 778, 763, 761, 763, 747, 758, 748, 747, 754, 749, 752, 753, 756, 762, 750, 753, 756, 749, 755, 757, 755, 756, 755, 744, 753, 758, 747, 751, 759, 751, 761, 755, 746, 752, 752, 749, 746, 752, 753, 755, 752, 755, 754, 754, 966, 937, 749, 759, 748, 747, 754, 749, 755, 750, 746, 754, 757, 752, 753, 745, 758, 755, 761, 753, 751, 755, 755, 752, 746, 756, 755, 746, 742, 751, 751, 749, 752, 751, 756, 756, 755, 742, 749, 754, 749, 756, 753, 751, 754, 752, 751, 754, 753, 749, 755, 756] C.ToArray 772.8 ms -> [766, 772, 755, 763, 758, 767, 763, 762, 761, 768, 769, 763, 770, 757, 765, 760, 766, 759, 764, 761, 760, 777, 1102, 881, 759, 765, 758, 762, 772, 761, 758, 757, 765, 769, 769, 761, 762, 762, 763, 760, 770, 764, 760, 768, 758, 766, 763, 770, 769, 761, 764, 761, 761, 767, 761, 762, 764, 757, 765, 766, 767, 771, 753, 762, 769, 768, 759, 764, 764, 760, 763, 763, 763, 763, 763, 767, 761, 771, 760, 765, 760, 758, 768, 770, 751, 771, 767, 771, 765, 763, 760, 765, 765, 769, 767, 767, 1193, 774, 767, 764] S.ToList 704.73 ms -> [682, 708, 705, 699, 705, 704, 695, 703, 702, 699, 701, 708, 699, 702, 703, 701, 701, 699, 701, 707, 707, 700, 701, 705, 700, 697, 706, 702, 701, 706, 699, 692, 702, 697, 707, 704, 697, 698, 699, 699, 702, 703, 698, 697, 702, 703, 702, 704, 694, 697, 707, 695, 711, 710, 700, 693, 703, 699, 699, 706, 698, 701, 703, 704, 698, 706, 700, 704, 701, 699, 702, 705, 694, 698, 709, 736, 1053, 704, 694, 700, 698, 696, 701, 700, 700, 706, 706, 692, 698, 707, 703, 695, 703, 699, 694, 708, 695, 694, 706, 695] S.ToArray 744.17 ms -> [746, 740, 725, 740, 739, 731, 746, 760, 735, 738, 740, 734, 744, 748, 737, 744, 745, 727, 736, 738, 728, 743, 745, 735, 748, 760, 739, 748, 762, 742, 741, 747, 733, 746, 758, 742, 742, 741, 724, 744, 747, 727, 740, 740, 729, 742, 757, 741, 740, 742, 726, 739, 746, 1133, 749, 737, 730, 740, 747, 733, 747, 752, 731, 747, 742, 730, 741, 749, 731, 749, 743, 730, 747, 742, 731, 737, 745, 734, 739, 735, 727, 743, 752, 731, 744, 742, 729, 740, 746, 731, 739, 746, 733, 745, 743, 733, 739, 742, 727, 737] C1.ToList 31.71 ms -> [35, 32, 32, 30, 31, 33, 31, 32, 32, 31, 31, 32, 32, 33, 32, 31, 31, 32, 31, 32, 32, 32, 31, 32, 33, 32, 31, 31, 31, 32, 31, 34, 31, 31, 32, 33, 32, 32, 31, 32, 34, 32, 31, 32, 33, 31, 32, 32, 31, 32, 32, 32, 32, 32, 32, 31, 31, 32, 31, 33, 30, 31, 32, 30, 30, 33, 32, 32, 34, 31, 31, 31, 31, 32, 31, 31, 31, 31, 32, 31, 31, 33, 31, 32, 32, 32, 33, 32, 31, 31, 31, 31, 31, 32, 32, 33, 32, 31, 31, 32] C1.ToArray 59.53 ms -> [63, 57, 58, 58, 57, 59, 59, 57, 60, 131, 127, 67, 58, 56, 59, 56, 57, 58, 58, 58, 57, 59, 60, 57, 57, 59, 60, 57, 57, 57, 58, 58, 58, 58, 57, 57, 61, 57, 58, 57, 57, 57, 57, 57, 58, 58, 58, 58, 57, 58, 59, 57, 58, 57, 57, 59, 58, 58, 59, 57, 59, 57, 56, 56, 59, 56, 56, 59, 57, 58, 58, 58, 57, 58, 59, 59, 58, 57, 58, 62, 65, 57, 57, 57, 58, 60, 59, 58, 59, 57, 58, 57, 58, 59, 58, 58, 58, 59, 60, 58] S1.ToList 82.78 ms -> [87, 82, 83, 83, 82, 82, 83, 84, 82, 83, 84, 84, 84, 82, 82, 84, 82, 84, 83, 84, 82, 82, 82, 81, 83, 83, 83, 84, 84, 82, 82, 83, 83, 83, 82, 83, 85, 83, 82, 82, 84, 82, 82, 83, 83, 83, 82, 82, 82, 83, 82, 83, 82, 84, 82, 83, 82, 83, 82, 82, 82, 84, 82, 83, 82, 82, 86, 83, 83, 82, 83, 83, 83, 82, 84, 82, 83, 81, 82, 82, 82, 82, 83, 83, 83, 82, 83, 84, 83, 82, 83, 83, 83, 82, 83, 84, 82, 82, 83, 83] S1.ToArray 122.3 ms -> [122, 119, 119, 120, 119, 120, 120, 121, 119, 119, 122, 120, 120, 120, 122, 120, 123, 120, 120, 120, 121, 123, 120, 120, 120, 121, 120, 121, 122, 120, 123, 119, 121, 118, 121, 120, 120, 120, 119, 124, 119, 121, 119, 120, 120, 120, 120, 120, 122, 121, 123, 230, 203, 123, 119, 119, 122, 119, 120, 120, 120, 122, 120, 121, 120, 121, 120, 121, 120, 121, 120, 120, 120, 121, 122, 121, 123, 119, 119, 119, 119, 121, 120, 120, 120, 122, 121, 122, 119, 120, 120, 121, 121, 120, 121, 120, 121, 118, 118, 118] C2.ToList 3.43 ms -> [5, 3, 4, 4, 4, 3, 4, 4, 4, 4, 4, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 4, 3, 3, 3, 3, 4, 3, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 6, 4, 4, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 4, 4, 4, 3, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 3, 3, 3, 3] C2.ToArray 3.48 ms -> [3, 3, 3, 3, 4, 4, 3, 4, 4, 4, 3, 4, 3, 3, 4, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 3, 4, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, 3, 4, 3, 3, 4, 3, 3, 4, 3, 3, 4, 4, 3, 3, 4, 3, 4, 4, 3, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 3, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 3] S2.ToList 41.47 ms -> [41, 41, 49, 67, 82, 41, 41, 40, 40, 40, 40, 40, 41, 40, 40, 40, 40, 40, 41, 40, 42, 42, 40, 40, 41, 41, 41, 40, 41, 40, 41, 40, 41, 40, 42, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 42, 41, 41, 41, 42, 40, 41, 40, 40, 40, 42, 40, 41, 42, 41, 42, 41, 42, 40, 41, 41, 41, 41, 41, 41, 41, 41, 40, 41, 40, 41, 41, 41, 40, 41, 41, 40, 40, 41, 41, 41, 41, 41, 43, 40, 40, 41, 42, 41] S2.ToArray 40.62 ms -> [42, 41, 44, 40, 40, 40, 40, 41, 41, 40, 41, 41, 41, 40, 41, 41, 40, 41, 41, 40, 41, 40, 40, 41, 42, 41, 41, 41, 40, 40, 40, 40, 40, 41, 41, 42, 40, 41, 41, 41, 41, 41, 40, 42, 40, 40, 41, 41, 41, 40, 41, 40, 40, 40, 40, 40, 41, 40, 40, 41, 40, 40, 40, 40, 41, 40, 41, 41, 41, 40, 41, 41, 40, 41, 40, 41, 42, 40, 41, 41, 42, 41, 41, 40, 41, 40, 41, 40, 41, 41, 40, 40, 40, 41, 41, 40, 40, 40, 40, 40] |
由于stackoverflow限制了答案的字符数,因此省略了group2和group3的示例列表。
如您所见,在大多数情况下使用
在处理运行时计算的
这种差异只能在非运行时计算的
并且,
当然,这只是我的机器上的结果,这些操作在不同的机器上花费的实际时间是不一样的,你可以在你的机器上找到上面使用的代码。
您需要做出选择的唯一原因是,您对
最好是
在实体框架6中,两个方法最终都调用同一个内部方法,但
1 2 3 | T[] array = new T[_size]; Array.Copy(_items, 0, array, 0, _size); return array; |
因此,
对于有兴趣在另一个Linq to SQL中使用此结果的任何人,例如
1 2 3 | from q in context.MyTable where myListOrArray.Contains(q.someID) select q; |
然后生成的SQL与您使用的MyListorArray列表或数组相同。现在我知道有些人可能会问为什么在这个语句之前还要枚举,但是从iqueryable vs(列表或数组)生成的SQL之间有区别。