我生成以下代码:
public override void Map(IEnumerable enumerable1){ List<int> list = new List<int>(); foreach (object obj2 in enumerable1) { }}
通过Emit
这是完整的代码:
MethodBuilder mapMethod = typeBuilder.DefineMethod("Map", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), new[] { typeof(IEnumerable) });ILGenerator il = mapMethod.GetILGenerator();LocalBuilder result = il.DeclareLocal(typeof(List<int>)); //0LocalBuilder item = il.DeclareLocal(typeof(object)); //1LocalBuilder enumeartor = il.DeclareLocal(typeof(IEnumerator)); //2LocalBuilder dispose = il.DeclareLocal(typeof(IDisposable)); //3Label labelWhile = il.DefineLabel();Label labelReturn = il.DefineLabel();Label labelMoveNext = il.DefineLabel();Label labelEndFinally = il.DefineLabel();//Create result ListConstructorInfo constructorInfo = (typeof(List<int>).GetConstructor(Type.EmptyTypes));il.Emit(OpCodes.Newobj, constructorInfo);il.Emit(OpCodes.Stloc_0, result);il.Emit(OpCodes.Ldarg_1);il.EmitCall(OpCodes.Callvirt, typeof(IEnumerable).GetMethod("GetEnumerator"), Type.EmptyTypes);il.Emit(OpCodes.Stloc_2, enumeartor);il.BeginExceptionBlock();il.Emit(OpCodes.Br_S, labelMoveNext);il.MarkLabel(labelWhile);il.Emit(OpCodes.Ldloc_2);il.EmitCall(OpCodes.Callvirt, typeof(IEnumerator).GetProperty("Current").GetGetMethod(), Type.EmptyTypes);il.Emit(OpCodes.Stloc_1, item);il.Emit(OpCodes.Ldloc_1);il.MarkLabel(labelMoveNext);il.Emit(OpCodes.Ldloc_2);il.EmitCall(OpCodes.Callvirt, typeof(IEnumerator).GetMethod("MoveNext"), Type.EmptyTypes);il.Emit(OpCodes.Brtrue_S, labelWhile);THE ISSUE IS HERE, I don't insert Leave instruction, but it there// il.Emit(OpCodes.Leave_S, labelReturn);il.BeginFinallyBlock();il.Emit(OpCodes.Ldloc_2);il.Emit(OpCodes.Isinst, typeof(IDisposable));il.Emit(OpCodes.Stloc_3, dispose);il.Emit(OpCodes.Ldloc_3);il.Emit(OpCodes.Brfalse_S, labelEndFinally);il.Emit(OpCodes.Ldloc_3);il.EmitCall(OpCodes.Callvirt, typeof(IDisposable).GetMethod("Dispose"), Type.EmptyTypes);il.MarkLabel(labelEndFinally);il.EndExceptionBlock();il.MarkLabel(labelReturn);il.Emit(OpCodes.Ret);
这是结果IL(见IL_001f):
.method public virtual instance void Map(class [mscorlib]System.Collections.IEnumerable A_1) cil managed{ // Code size 54 (0x36) .maxstack 5 .locals init (class [mscorlib]System.Collections.Generic.List`1<int32> V_0, object V_1, class [mscorlib]System.Collections.IEnumerator V_2, class [mscorlib]System.IDisposable V_3) IL_0000: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor() IL_0005: stloc.0 IL_0006: ldarg.1 IL_0007: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.IEnumerable::GetEnumerator() IL_000c: stloc.2 .try { IL_000d: br.s IL_0017 IL_000f: ldloc.2 IL_0010: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current() IL_0015: stloc.1 IL_0016: ldloc.1 IL_0017: ldloc.2 IL_0018: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() IL_001d: brtrue.s IL_000f THE ISSUE IS HERE IL_001f: leave IL_0035 } // end .try finally { IL_0024: ldloc.2 IL_0025: isinst [mscorlib]System.IDisposable IL_002a: stloc.3 IL_002b: ldloc.3 IL_002c: brfalse.s IL_0034 IL_002e: ldloc.3 IL_002f: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_0034: endfinally } // end handler IL_0035: ret} // end of method ForeachType::Map
你能否澄清为何出现离职指示?
解决方法:
Hans Passant感谢您的建议.在code之后解释了发生了什么.
public virtual void BeginFinallyBlock() { if (m_currExcStackCount==0) { throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock")); } __ExceptionInfo current = m_currExcStack[m_currExcStackCount-1]; int state = current.GetCurrentState(); Label endLabel = current.GetEndLabel(); int catchEndAddr = 0; if (state != __ExceptionInfo.State_Try) { // generate leave for any preceeding catch clause this.Emit(OpCodes.Leave, endLabel); catchEndAddr = m_length; } MarkLabel(endLabel); Label finallyEndLabel = this.DefineLabel(); current.SetFinallyEndLabel(finallyEndLabel); // generate leave for try clause this.Emit(OpCodes.Leave, finallyEndLabel); HERE'S THE ANSWER if (catchEndAddr == 0) catchEndAddr = m_length; current.MarkFinallyAddr(m_length, catchEndAddr); }
来源:https://www.icode9.com/content-1-292851.html
联系客服