我只是以此来嘲笑你的代码
foreach(var v in Enumerable.Range(1,10).Skip(1)) v.Dump();
这是生成的IL。
IL_0001: nop IL_0002: ldc.i4.1 IL_0003: ldc.i4.s 0A IL_0005: call System.Linq.Enumerable.RangeIL_000A: ldc.i4.1 IL_000B: call System.Linq.Enumerable.Skip//Call to SkipIL_0010: callvirt System.Collections.Generic.IEnumerable<System.Int32>.GetEnumeratorIL_0015: stloc.1 // CSSkip00IL_0016: br.s IL_0026IL_0018: ldloc.1 // CSIEnumerator<int> e = ((IEnumerable<int>)values).GetEnumerator();//Get the enumeratortry{ int m;//This variable is here prior to c#5.0 while(e.MoveNext()) {//int m; is declared here starting from c#5.0 m = (int)(int)e.Current; //Your pre here }}finally{ if (e != null) ((IDisposable)e).Dispose();}00IL_0019: callvirt System.Collections.Generic.IEnumerator<System.Int32>.get_CurrentIL_001E: stloc.0 // vIL_001F: ldloc.0 // vIL_0020: call LINQPad.Extensions.DumpIL_0025: pop IL_0026: ldloc.1 // CSVeryLongRunningMethodThatReturnsEnumerable00IL_0027: callvirt System.Collections.IEnumerator.MoveNextIL_002C: stloc.2 // CSforeach(var obj in VeryLongRunningMethodThatReturnsEnumerable()){ //Do something with that obj}01IL_002D: ldloc.2 // CS01IL_002E: brtrue.s IL_0018IL_0030: leave.s IL_0042IL_0032: ldloc.1 // CS00IL_0033: ldnull IL_0034: ceq IL_0036: stloc.2 // CS01IL_0037: ldloc.2 // CS01IL_0038: brtrue.s IL_0041IL_003A: ldloc.1 // CS00IL_003B: callvirt System.IDisposable.DisposeIL_0040: nop IL_0041: endfinally
如您所见,仅被调用一次。
等效的C#代码看起来像这样
考虑下面的代码,如果foreach
在每次迭代中调用,那将是一场噩梦。语言设计中的巨大缺陷。幸运的是它没有那样做。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)