for与foreach从性能上来讲几乎是一样的,主要区别在栈内存的使用上。foreach会涉及迭代器,而迭代器会使用栈内存。从某种程度来说,foreach其实是一种语法糖,甚至连微软也推荐在循环中操作集合涉及到添加或移除项时只使用for,否则可能会产生不可预知的副作用。
测试方式是for 和 foreach 分别遍历一个数组一百万次。
测试1:遍历数组时,每个元素只访问一次
测试2:遍历数组时,每个元素访问多次
测试环境
1. macOS
2. Mono Runtime
Program.cs
using System;
using System.Diagnostics;
class Program {
static void Main() {
Console.WriteLine ("Runing Csharp Loop Performace Test.");
const int loop_count = 1000 * 1000 * 100;
int[] array = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
// 测试 for 性能
var watch_1 = Stopwatch.StartNew();
for (int i = 0; i < loop_count; i++) {
TestCase.case_for(array);
}
watch_1.Stop();
// 测试 foreach 性能
var watch_2 = Stopwatch.StartNew();
for (int i = 0; i < loop_count; i++) {
TestCase.case_foreach(array);
}
watch_2.Stop();
Console.WriteLine ("case for: " +
((double)(watch_1.Elapsed.TotalMilliseconds * 1000000) / loop_count).ToString("0.0 ns"));
Console.WriteLine ("case foreach: " +
((double)(watch_2.Elapsed.TotalMilliseconds * 1000000) / loop_count).ToString("0.0 ns"));
}
}
测试1[for 测试]
class TestCase {
public static int case_for(int[] array) {
int result = 0;
for (int i = 0; i < array.Length; i++) {
result += array[i];
}
return result;
}
}
测试1 [foreach 测试]
class TestCase {
public static int case_foreach(int[] array) {
int result = 0;
foreach (int value in array) {
result += value;
}
return result;
}
}
测试1耗时
Runing Csharp Loop Performace Test.
case for: 12.1 ns
case foreach: 12.6 ns
测试2 [for 测试]
class TestCase {
public static int case_foreach(int[] array) {
int result = 0;
foreach (int value in array) {
result += value;
result += value;
result += value;
}
return result;
}
}
测试2 耗时
uning Csharp Loop Performace Test.
case for: 20.5 ns
case foreach: 15.4 ns
结论
for的性能是要比foreach要高出一些,但测试1和测试2对比。 需要频繁去访问集合中的元素
result += array[i];
反而会比用foreach还要慢,因为foreach已经把元素取出后无需再次访问集合,元素已经在栈内存中。
所以在使用循环时,也需要考虑实际场景。如果循环内只会访问一次元素,则用for,如果访问多次元素则用foreach,但从易用性以及风格统一的考虑推荐使用foreach,除非有特殊需求再考虑使用for循环。