关于for与foreach的争论,一直都存在。不过有些人只是拿array来测试,有些人只是拿arraylist测试,有些拿valuetype测试,有些拿引用类型测试,测试结果大相径庭,让我不知道相信哪个。于是今天自己测试了一下。
我没有做很全面的测试,只选择了其中四种,而且四种都是针对引用类型来测试的,而没有针对值类型测试。四种测试方法如下:
1、使用Array,也就是object[],比较for与foreach循环的耗时。
2、使用Array,但存放自定义类型,比较for与foreach循环的耗时。
3、使用ArrayList,存放简单的object类型,比较for与foreach循环的耗时。
4、使用ArrayList,存放自定义类型,比较for与foreach循环的耗时。
注1:我没有使用值类型来测试。foreach实际上是转换为了对枚举器的调用,而枚举器返回类型是object类型,所以值类型的数组在每次foreach访问的时候都会有一次装箱和一次拆箱的操作,这个会很大程度的影响遍历的性能。因此对值类型数组的遍历for的性能更好是有可能的。
注2:我使用的自定义类型的定义如下:


注3:我没有测试自定义的强类型集合或者其他实现了IList接口的类型比如DataTable,因为我觉得具体情况要取决于枚举器的实现,而实际上我们的强类型集合在继承了IList或者CollectionBase之后一般不会实现自定义的枚举器,即使实现了也是在.net的枚举器基础上做了表面上的修改而不会修改其核心算法,因此结果应该与ArrayList的测试结果一样。
注4:Dll以及Console都是在Debug模式测试的。
具体测试代码如下:
Dll中的测试方法:




















































































































































Console控制台的调用:






























































为了去掉其他如.net机制等造成的影响,编译完成后,我通过cmd.exe先执行了几遍调用,然后开始真正的测试。
最终输出如下:
please input command:
test
ArrayTest
for: 15.625
foreach: 15.625
MyObjectArrayTest
for: 2250
foreach: 812.5
SimpleObjectListTest
for: 15.625
foreach: 31.25
MyObjectListTest
for: 2312.5
foreach: 859.375
please input command:
exit
will exit.
// 注:上面的调用是为了消除.net机制等引起的第一次执行可能引起的额外影响。下面真正开始测试。
E:/My Projects/ConsoleTester/bin/Debug>ConsoleTester.exe
please input command:
test
ArrayTest
for: 15.625
foreach: 15.625
MyObjectArrayTest
for: 2046.875
foreach: 812.5
SimpleObjectListTest
for: 31.25
foreach: 15.625
MyObjectListTest
for: 2187.5
foreach: 890.625
please input command:
test
ArrayTest
for: 31.25
foreach: 15.625
MyObjectArrayTest
for: 2187.5
foreach: 843.75
SimpleObjectListTest
for: 31.25
foreach: 15.625
MyObjectListTest
for: 2203.125
foreach: 859.375
please input command:
test
ArrayTest
for: 15.625
foreach: 15.625
MyObjectArrayTest
for: 2312.5
foreach: 812.5
SimpleObjectListTest
for: 31.25
foreach: 15.625
MyObjectListTest
for: 2375
foreach: 843.75
please input command:
test
ArrayTest
for: 15.625
foreach: 15.625
MyObjectArrayTest
for: 2359.375
foreach: 828.125
SimpleObjectListTest
for: 15.625
foreach: 15.625
MyObjectListTest
for: 2343.75
foreach: 843.75
please input command:
test
ArrayTest
for: 15.625
foreach: 31.25
MyObjectArrayTest
for: 2218.75
foreach: 812.5
SimpleObjectListTest
for: 15.625
foreach: 46.875
MyObjectListTest
for: 2359.375
foreach: 859.375
please input command:
test
ArrayTest
for: 15.625
foreach: 31.25
MyObjectArrayTest
for: 2171.875
foreach: 843.75
SimpleObjectListTest
for: 31.25
foreach: 15.625
MyObjectListTest
for: 2375
foreach: 859.375
please input command:
test
ArrayTest
for: 15.625
foreach: 31.25
MyObjectArrayTest
for: 2203.125
foreach: 812.5
SimpleObjectListTest
for: 31.25
foreach: 15.625
MyObjectListTest
for: 2343.75
foreach: 875
please input command:
test
ArrayTest
for: 15.625
foreach: 15.625
MyObjectArrayTest
for: 2250
foreach: 812.5
SimpleObjectListTest
for: 15.625
foreach: 31.25
MyObjectListTest
for: 2312.5
foreach: 859.375
please input command:
test
ArrayTest
for: 15.625
foreach: 15.625
MyObjectArrayTest
for: 2265.625
foreach: 828.125
SimpleObjectListTest
for: 15.625
foreach: 31.25
MyObjectListTest
for: 2343.75
foreach: 859.375
please input command:
test
ArrayTest
for: 15.625
foreach: 15.625
MyObjectArrayTest
for: 2250
foreach: 843.75
SimpleObjectListTest
for: 15.625
foreach: 31.25
MyObjectListTest
for: 2406.25
foreach: 843.75
please input command:
从上面的结果来看,测试结果有些动荡,不过我们通过大多数情况,就可以得到一些一般性结论。具体结论我也就不说了。虽然测试的覆盖面并不是很全,不过个人觉得至少代表了我们实际应用中的大部分情况。
测试完毕。
顺便贴下Dll反编译的结果:(有人说反编译发现foreach都变成了for,事实好像不是这样的)



























































































































