Fra*_*ger 488 .net linq performance
我经常遇到我想在我声明它的地方评估查询的情况.这通常是因为我需要多次迭代它并且计算起来很昂贵.例如:
string raw = "...";
var lines = (from l in raw.Split('\n')
let ll = l.Trim()
where !string.IsNullOrEmpty(ll)
select ll).ToList();
Run Code Online (Sandbox Code Playgroud)
这很好用.但是,如果我不打算修改结果,那么我不妨打电话给ToArray()而不是ToList().
我想知道是否ToArray()通过第一次调用实现,ToList()因此内存效率低于仅调用ToList().
我疯了吗?我应该只是打电话ToArray()- 安全且安全地知道内存不会被分配两次吗?
Jar*_*Par 340
除非您只需要一个数组来满足其他约束,否则您应该使用它ToList.在大多数情况下ToArray会分配更多的内存ToList.
两者都使用数组进行存储,但ToList具有更灵活的约束.它需要数组至少与集合中元素的数量一样大.如果数组较大,那不是问题.但是,ToArray需要将数组的大小精确地调整为元素的数量.
为了满足这种约束,ToArray通常会进行一次分配ToList.一旦它有一个足够大的数组,它就会分配一个完全正确大小的数组,并将元素复制回该数组.唯一能避免这种情况的是当数组的增长算法恰好与需要存储的元素数量一致时(绝对是少数).
编辑
有几个人问我在List<T>数值中有多余的未使用内存的后果.
这是一个有效的问题.如果创建的集合是长期存在的,在创建后永远不会被修改并且很有可能在Gen2堆中着陆,那么您可能最好先采取额外的分配ToArray.
总的来说,虽然我发现这是罕见的情况.更常见的是看到很多ToArray调用立即传递给其他短暂的内存使用,在这种情况下ToList显然更好.
这里的关键是剖析,剖析,然后再详细介绍一些.
mqp*_*mqp 166
性能差异将是微不足道的,因为它List<T>是作为动态大小的阵列实现的.调用ToArray()(使用内部Buffer<T>类来增长数组)或ToList()(调用List<T>(IEnumerable<T>)构造函数)将最终成为将它们放入数组并增长数组直到它适合所有数组的问题.
如果您希望具体确认这一事实,请查看Reflector中相关方法的实现 - 您将看到它们归结为几乎完全相同的代码.
Tyr*_*rrz 79
外面是 2020 年,每个人都在使用 .NET Core 3.1,所以我决定使用 Benchmark.NET 运行一些基准测试。
TL;DR:ToArray() 在性能方面更好,如果您不打算改变集合,则可以更好地传达意图。
[MemoryDiagnoser]
public class Benchmarks
{
[Params(0, 1, 6, 10, 39, 100, 666, 1000, 1337, 10000)]
public int Count { get; set; }
public IEnumerable<int> Items => Enumerable.Range(0, Count);
[Benchmark(Description = "ToArray()", Baseline = true)]
public int[] ToArray() => Items.ToArray();
[Benchmark(Description = "ToList()")]
public List<int> ToList() => Items.ToList();
public static void Main() => BenchmarkRunner.Run<Benchmarks>();
}
Run Code Online (Sandbox Code Playgroud)
结果是:
BenchmarkDotNet=v0.12.0, OS=Windows 10.0.14393.3443 (1607/AnniversaryUpdate/Redstone1)
Intel Core i5-4460 CPU 3.20GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
Frequency=3124994 Hz, Resolution=320.0006 ns, Timer=TSC
.NET Core SDK=3.1.100
[Host] : .NET Core 3.1.0 (CoreCLR 4.700.19.56402, CoreFX 4.700.19.56404), X64 RyuJIT
DefaultJob : .NET Core 3.1.0 (CoreCLR 4.700.19.56402, CoreFX 4.700.19.56404), X64 RyuJIT
| Method | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---------- |------ |--------------:|------------:|------------:|--------------:|------:|--------:|--------:|------:|------:|----------:|
| ToArray() | 0 | 7.357 ns | 0.2096 ns | 0.1960 ns | 7.323 ns | 1.00 | 0.00 | - | - | - | - |
| ToList() | 0 | 13.174 ns | 0.2094 ns | 0.1958 ns | 13.084 ns | 1.79 | 0.05 | 0.0102 | - | - | 32 B |
| | | | | | | | | | | | |
| ToArray() | 1 | 23.917 ns | 0.4999 ns | 0.4676 ns | 23.954 ns | 1.00 | 0.00 | 0.0229 | - | - | 72 B |
| ToList() | 1 | 33.867 ns | 0.7350 ns | 0.6876 ns | 34.013 ns | 1.42 | 0.04 | 0.0331 | - | - | 104 B |
| | | | | | | | | | | | |
| ToArray() | 6 | 28.242 ns | 0.5071 ns | 0.4234 ns | 28.196 ns | 1.00 | 0.00 | 0.0280 | - | - | 88 B |
| ToList() | 6 | 43.516 ns | 0.9448 ns | 1.1949 ns | 42.896 ns | 1.56 | 0.06 | 0.0382 | - | - | 120 B |
| | | | | | | | | | | | |
| ToArray() | 10 | 31.636 ns | 0.5408 ns | 0.4516 ns | 31.657 ns | 1.00 | 0.00 | 0.0331 | - | - | 104 B |
| ToList() | 10 | 53.870 ns | 1.2988 ns | 2.2403 ns | 53.415 ns | 1.77 | 0.07 | 0.0433 | - | - | 136 B |
| | | | | | | | | | | | |
| ToArray() | 39 | 58.896 ns | 0.9441 ns | 0.8369 ns | 58.548 ns | 1.00 | 0.00 | 0.0713 | - | - | 224 B |
| ToList() | 39 | 138.054 ns | 2.8185 ns | 3.2458 ns | 138.937 ns | 2.35 | 0.08 | 0.0815 | - | - | 256 B |
| | | | | | | | | | | | |
| ToArray() | 100 | 119.167 ns | 1.6195 ns | 1.4357 ns | 119.120 ns | 1.00 | 0.00 | 0.1478 | - | - | 464 B |
| ToList() | 100 | 274.053 ns | 5.1073 ns | 4.7774 ns | 272.242 ns | 2.30 | 0.06 | 0.1578 | - | - | 496 B |
| | | | | | | | | | | | |
| ToArray() | 666 | 569.920 ns | 11.4496 ns | 11.2450 ns | 571.647 ns | 1.00 | 0.00 | 0.8688 | - | - | 2728 B |
| ToList() | 666 | 1,621.752 ns | 17.1176 ns | 16.0118 ns | 1,623.566 ns | 2.85 | 0.05 | 0.8793 | - | - | 2760 B |
| | | | | | | | | | | | |
| ToArray() | 1000 | 796.705 ns | 16.7091 ns | 19.8910 ns | 796.610 ns | 1.00 | 0.00 | 1.2951 | - | - | 4064 B |
| ToList() | 1000 | 2,453.110 ns | 48.1121 ns | 65.8563 ns | 2,460.190 ns | 3.09 | 0.10 | 1.3046 | - | - | 4096 B |
| | | | | | | | | | | | |
| ToArray() | 1337 | 1,057.983 ns | 20.9810 ns | 41.4145 ns | 1,041.028 ns | 1.00 | 0.00 | 1.7223 | - | - | 5416 B |
| ToList() | 1337 | 3,217.550 ns | 62.3777 ns | 61.2633 ns | 3,203.928 ns | 2.98 | 0.13 | 1.7357 | - | - | 5448 B |
| | | | | | | | | | | | |
| ToArray() | 10000 | 7,309.844 ns | 160.0343 ns | 141.8662 ns | 7,279.387 ns | 1.00 | 0.00 | 12.6572 | - | - | 40064 B |
| ToList() | 10000 | 23,858.032 ns | 389.6592 ns | 364.4874 ns | 23,759.001 ns | 3.26 | 0.08 | 12.6343 | - | - | 40096 B |
// * Hints *
Outliers
Benchmarks.ToArray(): Default -> 2 outliers were removed (35.20 ns, 35.29 ns)
Benchmarks.ToArray(): Default -> 2 outliers were removed (38.51 ns, 38.88 ns)
Benchmarks.ToList(): Default -> 1 outlier was removed (64.69 ns)
Benchmarks.ToArray(): Default -> 1 outlier was removed (67.02 ns)
Benchmarks.ToArray(): Default -> 1 outlier was removed (130.08 ns)
Benchmarks.ToArray(): Default -> 1 outlier was detected (541.82 ns)
Benchmarks.ToArray(): Default -> 1 outlier was removed (7.82 us)
// * Legends *
Count : Value of the 'Count' parameter
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Median : Value separating the higher half of all measurements (50th percentile)
Ratio : Mean of the ratio distribution ([Current]/[Baseline])
RatioSD : Standard deviation of the ratio distribution ([Current]/[Baseline])
Gen 0 : GC Generation 0 collects per 1000 operations
Gen 1 : GC Generation 1 collects per 1000 operations
Gen 2 : GC Generation 2 collects per 1000 operations
Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
1 ns : 1 Nanosecond (0.000000001 sec)
Run Code Online (Sandbox Code Playgroud)
Jep*_*sen 44
(七年后......)
其他(好)答案集中在将发生的微观性能差异上.
此信息仅仅是一个补充提语义差别之间存在IEnumerator<T>(产生由阵列T[])相比于由一个返回List<T>.
通过示例最佳说明:
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);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码将运行,没有异常并产生输出:
1 2 3 4 5 6 7 8 900 10
这表明IEnumarator<int>由an返回的数据int[]不会跟踪自创建枚举器以来数组是否已被修改.
请注意,我将局部变量声明source为IList<int>.通过这种方式,我确保C#编译器不会将foreach语句优化为等同于for (var idx = 0; idx < source.Length; idx++) { /* ... */ }循环的东西.如果我使用C#编译器可能会这样做var source = ...;.在我当前版本的.NET框架中,这里使用的实际枚举器是非公共引用类型,System.SZArrayHelper+SZGenericArrayEnumerator`1[System.Int32]但当然这是一个实现细节.
现在,如果我改变.ToArray()成.ToList(),我只得到:
1 2 3 4 5
随后是一个System.InvalidOperationException爆炸性的说法:
收集被修改; 枚举操作可能无法执行.
在这种情况下,底层枚举器是public mutable value-type System.Collections.Generic.List`1+Enumerator[System.Int32](IEnumerator<int>在这种情况下,盒子装在盒子里,因为我使用IList<int>).
总之,由枚举器生成的枚举器List<T>会跟踪列表在枚举期间是否发生更改,而生成的枚举T[]器则不会.因此,在.ToList()和之间选择时要考虑这种差异.ToArray().
人们经常添加一个额外的 .ToArray()或.ToList()绕过一个集合来跟踪它是否在枚举器的生命周期中被修改.
(如果有人想知道如何在List<>跟踪上收集是否被修改,有一个私人领域_version在这个类,这是每次改变的List<>更新.)
EMP*_*EMP 27
我同意@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
Run Code Online (Sandbox Code Playgroud)
每个源数组/ List都有1000个元素.所以你可以看到时间和内存的差异可以忽略不计.
我的结论是:你也可以使用ToList(),因为a List<T>提供了比数组更多的功能,除非几个字节的内存对你很重要.
Guf*_*ffa 19
内存将始终分配两次 - 或接近该内存.由于无法调整数组大小,因此两种方法都将使用某种机制来收集不断增长的集合中的数据.(好吧,List是一个不断增长的集合.)
List使用数组作为内部存储,并在需要时将容量加倍.这意味着平均2/3的项目至少重新分配一次,其中一半重新分配至少两次,其中一半重新分配至少三次,依此类推.这意味着每个项目平均重新分配1.3次,这不是很大的开销.
还要记住,如果要收集字符串,集合本身只包含对字符串的引用,字符串本身不会重新分配.
Vit*_*kov 19
ToList()如果您在IEnumerable<T>(例如,来自ORM)上使用它通常是首选.如果在开头不知道序列的长度,则ToArray()创建像List这样的动态长度集合,然后将其转换为数组,这需要额外的时间.
Sco*_*pey 15
Edit: The last part of this answer is not valid. However, the rest is still useful information, so I'll leave it.
I know this is an old post, but after having the same question and doing some research, I have found something interesting that might be worth sharing.
First, I agree with @mquander and his answer. He is correct in saying that performance-wise, the two are identical.
However, I have been using Reflector to take a look at the methods in the System.Linq.Enumerable extensions namespace, and I have noticed a very common optimization.
Whenever possible, the IEnumerable<T> source is cast to IList<T> or ICollection<T> to optimize the method. For example, look at ElementAt(int).
Interestingly, Microsoft chose to only optimize for IList<T>, but not IList. It looks like Microsoft prefers to use the IList<T> interface.
System.Array只实现IList,因此它不会受益于任何这些扩展优化.
因此,我认为最佳做法是使用该.ToList()方法.
如果您使用任何扩展方法,或将列表传递给另一个方法,则可能会对其进行优化IList<T>.
naw*_*fal 12
你应该立足自己的决定去ToList或ToArray基于什么理想的设计选择.如果您想要一个只能通过索引迭代和访问的集合,请选择ToArray.如果你想要在以后添加和删除集合的其他功能而没有太多的麻烦,那么做一个ToList(不是真的你不能添加到数组,但这通常不是正确的工具).
如果性能很重要,您还应该考虑哪些操作更快.实际上,你不会打电话ToList或ToArray一百万次,但可能会在获得的收集上工作一百万次.在这方面[]比较好,因为List<>是[]有一些开销.请参阅此线程以进行效率比较:哪一个更有效:List <int>或int []
在我不久前的测试中,我发现ToArray速度更快了.而且我不确定测试有多么偏差.但性能差异是如此微不足道,只有当您在循环中运行这些查询数百万次时才能注意到这一点.
Erd*_*tur 12
一个非常晚的答案,但我认为这将有助于谷歌.
他们在使用linq创建时都很糟糕.如有必要,它们都实现相同的代码来调整缓冲区大小.ToArray内部使用一个类转换IEnumerable<>为数组,通过分配一个包含4个元素的数组.如果这还不够,可以通过创建一个新的数组,将当前大小加倍,并将当前数组复制到该数组,从而使其大小增加一倍.最后,它会分配一个新的项目数量.如果您的查询返回129个元素,那么ToArray将进行6次分配和内存复制操作以创建256个元素数组,而不是另一个129要返回的数组.对于记忆效率这么多.
ToList执行相同的操作,但它会跳过最后一次分配,因为您可以在将来添加项目.列表不关心它是从linq查询创建还是手动创建.
创建列表更好的内存,但更糟糕的是cpu,因为列表是一个通用的解决方案,每个操作都需要范围检查,除了.net的内部范围检查数组.
因此,如果您将遍历结果集太多次,那么数组是好的,因为它意味着比列表更少的范围检查,并且编译器通常优化数组以进行顺序访问.
如果在创建容量参数时指定容量参数,则列表的初始化分配会更好.在这种情况下,假设您知道结果大小,它将仅分配一次数组.ToListlinq没有指定提供它的重载,所以我们必须创建我们的扩展方法,创建一个具有给定容量的列表然后使用List<>.AddRange.
要完成这个答案,我必须写下面的句子
Str*_*ior 12
我发现人们在这里做的其他基准测试缺乏,所以这里是我的解决方案.如果您发现我的方法有问题,请告诉我.
/* 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
Run Code Online (Sandbox Code Playgroud)
您可以在此处下载LINQPad脚本.
调整上面的代码,你会发现:

ints而不是strings 时,差异不太明显.structs而不是strings需要花费更多时间,但并没有真正改变比率.这与最高投票答案的结论一致:
ToList() 一直运行得更快,如果你不打算长时间坚持结果,那将是一个更好的选择.@JonHanna指出,根据Select它的实现,一个ToList()或一个ToArray()实现可以提前预测产生的集合的大小.替换.Select(i => i)上面的代码会Where(i => true) 产生非常类似的结果,并且无论.NET实现如何都更有可能这样做.
这是一个古老的问题 - 但是为了绊倒它的用户的利益,还有"Memoizing"Enumerable的替代方案 - 它具有缓存和停止Linq语句的多个枚举的效果,这就是ToArray()即使从不使用列表或数组的集合属性,也会使用ToList().
Memoize在RX/System.Interactive lib中可用,并在此解释: 更多LINQ with System.Interactive
(来自Bart De'Smet的博客,如果您与Linq一起使用很多对象,这是一个强烈推荐的读物)
一种选择是添加您自己的返回readonly 的 ICollection<T>扩展方法。当您不想使用数组/列表的索引属性或从列表中添加/删除时,这可能比使用ToListor更好。ToArray
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();
}
}
Run Code Online (Sandbox Code Playgroud)
单元测试:
[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);
}
}
Run Code Online (Sandbox Code Playgroud)
老问题,但始终有新提问者。
根据System.Linq.Enumerable的来源,ToList只需返回 a new List(source),而ToArray使用 a则new Buffer<T>(source).ToArray()返回 a T[]。
关于内存分配:
IEnumerable<T>在唯一对象上运行时,ToArray请比 多分配一次内存ToList。但大多数情况下你不必关心它,因为GC会在需要时进行垃圾收集。
关于运行时效率:
质疑这个问题的人可以在自己的机器上运行以下代码,你就会得到答案。
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);
}
Run Code Online (Sandbox Code Playgroud)
我在我的机器上得到了这些结果:
第1组:
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]
Run Code Online (Sandbox Code Playgroud)
第2组:
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
Run Code Online (Sandbox Code Playgroud)
第三组:
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
Run Code Online (Sandbox Code Playgroud)
第4组:
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]
Run Code Online (Sandbox Code Playgroud)
第5组:
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, 74
ToListAsync<T>()是优选的。
在实体框架 6 中,这两个方法最终都会调用相同的内部方法,但在最后ToArrayAsync<T>()调用,其实现为list.ToArray()
T[] array = new T[_size];
Array.Copy(_items, 0, array, 0, _size);
return array;
Run Code Online (Sandbox Code Playgroud)
因此ToArrayAsync<T>()有一些开销,因而ToListAsync<T>()是优选的。
| 归档时间: |
|
| 查看次数: |
83497 次 |
| 最近记录: |