打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
c# – 为什么ILGenerator将Leave指令插入Foreach语句

我生成以下代码:

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
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
实体类编程的最佳伴侣——高效的实体类复制
自己动手开发编译器(十二)生成托管代码
【原创】颠覆C#王权的“魔比斯环” — 实现AOP框架的终极利器
一个通用快速的反射方法调用
C#通过Emit动态生成代码
C# 反射之动态生成dll/exe
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服