und*_*ned 14 c# performance ienumerable list
我与我的同事有一点争议(这非常接近圣战:))关于通过枚举VS通过枚举访问列表的性能.为了操作一些事实,我写了以下测试:
static void Main(string[] args)
{
const int count = 10000000;
var stopwatch = new Stopwatch();
var list = new List<int>(count);
var rnd = new Random();
for (int i = 0; i < count; i++)
{
list.Add( rnd.Next());
}
const int repeat = 20;
double indeces = 0;
double forEach = 0;
for (int iteration = 0; iteration < repeat; iteration++)
{
stopwatch.Restart();
long tmp = 0;
for (int i = 0; i < count; i++)
{
tmp += list[i];
}
indeces += stopwatch.Elapsed.TotalSeconds;
stopwatch.Restart();
foreach (var integer in list)
{
tmp += integer;
}
forEach += stopwatch.Elapsed.TotalSeconds;
}
Console.WriteLine(indeces /repeat);
Console.WriteLine(forEach /repeat);
}
Run Code Online (Sandbox Code Playgroud)
实际上,它只是访问元素.
正如我所料,索引访问速度更快.这是我的机器上发布版本的结果:
0.0347//index access
0.0737//enumerating
Run Code Online (Sandbox Code Playgroud)
但是,我决定改变测试一点:
//the same as before
...
IEnumerable<int> listAsEnumerable = list;
//the same as before
...
foreach (var integer in listAsEnumerable)
{
tmp += integer;
}
...
Run Code Online (Sandbox Code Playgroud)
现在输出如下:
0.0321//index access
0.1246//enumerating (2x slower!)
Run Code Online (Sandbox Code Playgroud)
如果我们通过接口枚举相同的列表,性能会 慢2倍!
这意味着"通过接口枚举比枚举实际列表慢2倍".
我的猜测是运行时使用不同的Enumerator
s:第一次测试中的列表和第二次测试中的一般列表.
Mar*_*ell 16
使用时List<T>
,foreach
实际上并没有使用IEnumerable<T>
界面; 相反,它使用List<T>.Enumerator
,这是一个struct
.在平凡的层面上,这意味着稍微减少间接 - 不必去引用,使用静态调用而不是虚拟调用 - 以及更直接的实现.
这些差异非常小,在任何明智的现实生活中,差异都是噪音.然而,如果测试可能略微显刚的foreach
表现.
为了扩展这个:foreach
实际上并不需要IEnumerable[<T>]
- 它可以纯粹在GetEnumerator()
/ .MoveNext()
/ .Current
/ .Dispose()
模式上工作; 这在2.0中的泛型之前尤为重要.
但是,只有在键入变量List<T>
(具有自定义GetEnumerator()
方法)时才可以执行此操作.一旦你有IEnumerable<T>
,它必须使用IEnumerator<T>