本日有时与发起不要用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的内容,更多相关内容请关注ki4网(www.ki4.cn)!