您好,欢迎访问一九零五行业门户网

c# 中的 for vs foreach的详细介绍

今天偶然与建议不要用for,可读性太差性能又低,可我个人认为要根据具体情况而定,毕竟for在大部分语言的关键字,可读性不可能因为一个关键字的替代而变好,多数取决于设计和编码习惯。
至于性能,打算写段代码对它们分别测试一下。
var arr = enumerable.range(0, 100000000).tolist(); var sw = stopwatch.startnew(); for(var i = 0;i < arr.count; i++){} sw.stop(); console.writeline("for loop takes : " + sw.elapsedticks); sw = stopwatch.startnew(); foreach(var x in arr){} sw.stop(); console.writeline("for loop takes : " + sw.elapsedticks);
先看生成的il
for循环的部分:
... il_0018: ldc.i4.0 il_0019: stloc.2 // i il_001a: br.s il_0022 il_001c: nop il_001d: nop il_001e: ldloc.2 // i il_001f: ldc.i4.1 il_0020: add il_0021: stloc.2 // i il_0022: ldloc.2 // i il_0023: ldloc.0 // arr il_0024: callvirt system.collections.generic.list<system.int32>.get_count il_0029: clt il_002b: stloc.s 04 // cs$4$0000 il_002d: ldloc.s 04 // cs$4$0000 il_002f: brtrue.s il_001c ...
除了il_0024中的callvirt会触发方法虚表查询外,几乎不存在任何高消耗的指令。再来看foreach的il部分:
... il_005a: ldloc.0 // arr il_005b: callvirt system.collections.generic.list<system.int32>.getenumerator il_0060: stloc.s 05 // cs$5$0001 il_0062: br.s il_006e il_0064: ldloca.s 05 // cs$5$0001 il_0066: call system.collections.generic.list<system.int32>+enumerator.get_current il_006b: stloc.3 // x il_006c: nop il_006d: nop il_006e: ldloca.s 05 // cs$5$0001 il_0070: call system.collections.generic.list<system.int32>+enumerator.movenext il_0075: stloc.s 04 // cs$4$0000 il_0077: ldloc.s 04 // cs$4$0000 il_0079: brtrue.s il_0064 il_007b: leave.s il_008c il_007d: ldloca.s 05 // cs$5$0001 il_007f: constrained. system.collections.generic.list<>.enumerator il_0085: callvirt system.idisposable.dispose il_008a: nop il_008b: endfinally il_008c: nop ...
首先可以看到很多方法调用,并且在循环体内部每次都要调用方法movenext。最后可以看到,有end finally,意味着这个循环外部包了一层try-finally。从il来看,foreach要比for慢的多了。
现在来看stopwatch的执行结果。
for loop takes : 764538 for loop takes : 1311252
for几乎快了一倍。
结论:编程语言提供的关键字是为了解决某种问题而存在,需要对具体的业务场景进行判断再决定,有关性能方面,一定要拿出数据说话。
以上就是c#, for vs foreach的内容。
其它类似信息

推荐信息