Enumerable.Range 与 for 循环的性能

jol*_*oft 5 .net c# performance for-loop enumerable

我想知道Enumerable.Range使用foreach循环的性能开销是什么。例如:

var stringArray = Enumerable.Range(0, 4).Select(i => string.Empty).ToArray();
Run Code Online (Sandbox Code Playgroud)

对比。

var stringArray = new string[4];
for (int i = 0; i < formatted.Length; i++)
{
    stringArray[i] = string.Empty;
}
Run Code Online (Sandbox Code Playgroud)

我发现了这些问题:

  1. 为什么 Enumerable.Range 比直接 yield 循环快?

  2. Enumerable.Range 实现

  3. Enumerable.Range 与传统 for 循环对 foreach 的思考

但是我担心Select最后我可能会实际上循环两次。但是,我喜欢使用该Range选项的优雅。

Gil*_*een 7

从以下测试中,for效率更高:(以毫秒为单位是 +-3 毫秒的差异 - 这是微不足道的..)

var watch = System.Diagnostics.Stopwatch.StartNew();
var stringArra1y = Enumerable.Range(0, 4).Select(i => string.Empty).ToArray();
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //3305

watch = System.Diagnostics.Stopwatch.StartNew();
var stringArray2 = new string[4];
for (int i = 0; i < stringArray2.Length; i++)
{
    stringArray2[i] = string.Empty;
}
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //1
Run Code Online (Sandbox Code Playgroud)

但是您可以代替使用Enumerable.Range().Selectuse .Repeat

var watch = System.Diagnostics.Stopwatch.StartNew();
var stringArra1y = Enumerable.Repeat(string.Empty, 4).ToArray();
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //391
Run Code Online (Sandbox Code Playgroud)

说完上述注意,您在这里谈论的是非常小的集合(4 个项目)。在较大的集合中,特别是如果您删除.ToArray()它,它的行为就不一样了:

var watch = System.Diagnostics.Stopwatch.StartNew();
var stringArra1y = Enumerable.Repeat(string.Empty, 100000);
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //360


watch = System.Diagnostics.Stopwatch.StartNew();
var stringArray2 = new string[100000];
for (int i = 0; i < stringArray2.Length; i++)
{
    stringArray2[i] = string.Empty;
}
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //1335
Run Code Online (Sandbox Code Playgroud)

但是我担心最后使用 Select 那么我实际上可能会循环两次

展望虽然参考源.RangeRepeat与一个实现yield return

static IEnumerable<int> RangeIterator(int start, int count) {
     for (int i = 0; i < count; i++) yield return start + i;
}
Run Code Online (Sandbox Code Playgroud)

所以它也被延迟执行,就像.Select它不会循环两次的意思一样。

并不是Stopwatch每次运行都使用返回不同的结果,而是总体思路如上所示

IMO,尤其是在小集合的情况下,通过这些微小的性能改进来提高可读性。当您已经遇到性能问题时,只有在获得更大的鱼(例如使用嵌套for循环List<>而不是使用 a HashSet<>)之后,才能处理这样的事情。