Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么ILGenerator在Foreach语句中插入LEVE指令_C#_Cil_Reflection.emit_Il_Ilgenerator - Fatal编程技术网

C# 为什么ILGenerator在Foreach语句中插入LEVE指令

C# 为什么ILGenerator在Foreach语句中插入LEVE指令,c#,cil,reflection.emit,il,ilgenerator,C#,Cil,Reflection.emit,Il,Ilgenerator,我生成以下代码: public override void Map(IEnumerable enumerable1) { List<int> list = new List<int>(); foreach (object obj2 in enumerable1) { } } 以下是结果IL(请参见IL001f): .method公共虚拟实例无效映射(类[mscorlib]System.Collections.IEnumerable A_1

我生成以下代码:

public override void Map(IEnumerable enumerable1)
{
    List<int> list = new List<int>();
    foreach (object obj2 in enumerable1)
    {
    }
}
以下是结果IL(请参见
IL001f
):

.method公共虚拟实例无效映射(类[mscorlib]System.Collections.IEnumerable A_1)cil托管
{
//代码大小54(0x36)
.maxstack 5
.locals init(类[mscorlib]System.Collections.Generic.List`1 V_0,
对象V_1,
类[mscorlib]System.Collections.IEnumerator V_2,
类[mscorlib]System.IDisposable V_3)
IL_0000:newobj实例无效类[mscorlib]System.Collections.Generic.List`1::.ctor()
IL_0005:stloc.0
IL_0006:ldarg.1
IL_0007:callvirt实例类[mscorlib]System.Collections.IEnumerator[mscorlib]System.Collections.IEnumerable::GetEnumerator()
IL_000c:stloc.2
尝试
{
IL_000d:br.s IL_0017
IL_000f:ldloc.2
IL_0010:callvirt实例对象[mscorlib]System.Collections.IEnumerator::get_Current()
IL_0015:stloc.1
IL_0016:ldloc.1
IL_0017:ldloc.2
IL_0018:callvirt实例bool[mscorlib]System.Collections.IEnumerator::MoveNext()
IL_001d:brtrue.s IL_000f
问题就在这里
IL_001f:离开IL_0035
}//结束,再试一次
最后
{
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实例void[mscorlib]System.IDisposable::Dispose()
IL_0034:最终结束
}//结束处理程序
IL_0035:ret
}//方法ForeachType::Map的结尾
请您澄清一下为什么会出现“离开”指令?

谢谢您的建议。下面解释发生了什么

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); 
}

我相信这是终止任何
try{}
块的IL要求。也许,但同样的手写代码有
leave.s
指令。如果我插入
leave.s
有两条说明我不确定我是否完全理解你在这里说的话,但是
leave
leave.s
是相同的说明,除了目标标签的允许范围。是的,相同,我没有插入
leave
说明。真奇怪。为什么相同的代码有不同的指令?手写的有leave.s和我的代码leave。只要看一看,它就很明显是从哪里来的。嗯,你能解释一下吗,对我来说,代码是正确的,但注释不是:)实际上是这个方法中的低代码块被注释了
//generate leave for try子句
,它添加了您正在寻找的假期-正如Ben指出的,代码中缺少
catch
子句意味着这个块,已注释的
//为任何前面的catch子句生成休假
是不相关的。
.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
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); 
}