public static IDisposable ForEachLoop(this ILGenerator il, Type elementType, LocalBuilder collection, out LocalBuilder currentElement) { Label lMoveNext = il.DefineLabel(); Label lWork = il.DefineLabel(); currentElement = il.DeclareLocal(elementType); //get collection enumerator LocalBuilder enumerator = il.DeclareLocal(typeof(IEnumerator)); #if DEBUG il.EmitWriteLine("foreach-begin"); #endif il.Emit(Ldloc, collection.LocalIndex); il.Emit(Callvirt, getEnumeratorMethod); il.Emit(Stloc, enumerator.LocalIndex); //immediately move to "move next" to start enumeration il.Emit(Br, lMoveNext); //iteration work block il.MarkLabel(lWork); #if DEBUG il.EmitWriteLine(" foreach-loop"); #endif //get current element il.Emit(Ldloc, enumerator.LocalIndex); il.Emit(Callvirt, getCurrentMethod); il.Emit(Unbox_Any, elementType); il.Emit(Stloc, currentElement.LocalIndex); return(il.After(() => { //"move next" block il.MarkLabel(lMoveNext); il.Emit(Ldloc, enumerator.LocalIndex); //load enumerator as an argument il.Emit(Callvirt, moveNextMethod); il.Emit(Brtrue, lWork); //if result is true, go to lWork //otherwise, dispose enumerator and exit //il.Emit(Ldloc, enumerator.LocalIndex); //il.Emit(Callvirt, disposeMethod); #if DEBUG il.EmitWriteLine("foreach-end"); #endif })); }
public static IDisposable ForLoop(this ILGenerator il, LocalBuilder max, out LocalBuilder loopCounter) { loopCounter = il.DeclareLocal(typeof(int)); //loop counter #if DEBUG il.EmitWriteLine("for-begin"); #endif il.Emit(Ldc_I4_0); il.Emit(Stloc, loopCounter.LocalIndex); Label lBody = il.DefineLabel(); //loop body start Label lExit = il.DefineLabel(); //final and return il.MarkLabel(lBody); //loop body starts here //load counter and max and compare them il.Emit(Ldloc, loopCounter.LocalIndex); il.Emit(Ldloc, max.LocalIndex); //il.Emit(Ldc_I4_3); il.Emit(Clt); //1 - less, 0 - equal or more (exit) il.Emit(Brfalse, lExit); //jump on 1 #if DEBUG il.EmitWriteLine(" for-loop"); #endif // loop body executes here LocalBuilder loopCounterAfter = loopCounter; return(il.After(() => { //increment loop counter il.Increment(loopCounterAfter); //loop again il.Emit(Br, lBody); il.MarkLabel(lExit); #if DEBUG il.EmitWriteLine("for-end"); #endif })); }