首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >On Error Resume Next的CIL实现

On Error Resume Next的CIL实现
EN

Stack Overflow用户
提问于 2016-10-16 00:11:06
回答 2查看 160关注 0票数 2

我一直在想:臭名昭著的VB.NET语句"On Error Resume Next“是如何转换成CIL的?它是否涉及到用try...catches包装每一行?

EN

回答 2

Stack Overflow用户

发布于 2016-10-16 00:45:47

转到。

您不能在一个方法中将try-catch与遗留错误处理结合起来。当您使用On Error Resume Next时,该方法中的每一行代码都会获得一个标签以及一个惟一的标识符。在伪C#代码中:

代码语言:javascript
复制
int currentId = 0;

Label1:
currentId = 1;
Line1();

Label2:
currentId = 2;
Line2();

Label3:
currentId = 3;
Line3();

Exit:

整个方法被包装在一个try catch中。当异常发生时,捕获处理程序将检查currentId并对行中的下一个标签执行一次简单的goto (并且设置了ProjectError )。在我们的例子中,它看起来像这样:

代码语言:javascript
复制
try
{
  ...
}
catch (Exception ex)
{
  ProjectData.SetProjectError(ex);

  if (currentId == 1) goto Label2;
  if (currentId == 2) goto Label3;
  if (currentId == 3) goto Exit;
}

请注意,这只是我通过反编译VB.NET应用程序获得的实现细节。唯一的契约行为是在On Error Resume Next中定义的行为,它基本上归结为“设置项目错误并继续执行下一条语句”。

票数 3
EN

Stack Overflow用户

发布于 2016-12-23 04:17:42

这就是了:

代码语言:javascript
复制
Public Sub A()
End Sub
Public Sub B()
End Sub
Public Sub C()
End Sub
Public Sub D()
End Sub
Public Sub E()
End Sub

Public Sub Test()
    A()
    On Error GoTo ErrorHandler
    B()
    Exit Sub
    C()
    ErrorHandler:
    D()
    Resume Next
    E()
End Sub

编译为(不带补充方法):

代码语言:javascript
复制
.method public static void  Test() cil managed
{
  // Code size       201 (0xc9)
  .maxstack  3
  .locals init (int32 V_0,
           int32 V_1,
           int32 V_2)
  IL_0000:  ldc.i4.1
  IL_0001:  stloc.2
  IL_0002:  call       void VBTest.Program::A()
  IL_0007:  call       void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
  IL_000c:  ldc.i4.2
  IL_000d:  stloc.0
  IL_000e:  ldc.i4.3
  IL_000f:  stloc.2
  IL_0010:  call       void VBTest.Program::B()
  IL_0015:  leave      IL_00c0
  IL_001a:  ldc.i4.5
  IL_001b:  stloc.2
  IL_001c:  call       void VBTest.Program::C()
  IL_0021:  ldc.i4.6
  IL_0022:  stloc.2
  IL_0023:  call       void VBTest.Program::D()
  IL_0028:  ldc.i4.7
  IL_0029:  stloc.2
  IL_002a:  call       void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
  IL_002f:  ldloc.1
  IL_0030:  brtrue.s   IL_0047
  IL_0032:  ldc.i4     0x800a0014
  IL_0037:  call       class [mscorlib]System.Exception [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::CreateProjectError(int32)
  IL_003c:  throw
  IL_003d:  ldc.i4.s   9
  IL_003f:  stloc.2
  IL_0040:  call       void VBTest.Program::E()
  IL_0045:  leave.s    IL_00c0
  IL_0047:  ldloc.1
  IL_0048:  ldc.i4.1
  IL_0049:  add
  IL_004a:  ldc.i4.0
  IL_004b:  stloc.1
  IL_004c:  switch     ( 
                        IL_007d,
                        IL_0000,
                        IL_0007,
                        IL_000e,
                        IL_0015,
                        IL_001a,
                        IL_0021,
                        IL_0028,
                        IL_003d,
                        IL_003d,
                        IL_0045)
  IL_007d:  leave.s    IL_00b5
  IL_007f:  ldloc.2
  IL_0080:  stloc.1
  IL_0081:  ldloc.0
  IL_0082:  switch     ( 
                        IL_0093,
                        IL_0047,
                        IL_0021)
  IL_0093:  leave.s    IL_00b5
  IL_0095:  isinst     [mscorlib]System.Exception
  IL_009a:  ldnull
  IL_009b:  cgt.un
  IL_009d:  ldloc.0
  IL_009e:  ldc.i4.0
  IL_009f:  cgt.un
  IL_00a1:  and
  IL_00a2:  ldloc.1
  IL_00a3:  ldc.i4.0
  IL_00a4:  ceq
  IL_00a6:  and
  IL_00a7:  endfilter
  IL_00a9:  castclass  [mscorlib]System.Exception
  IL_00ae:  call       void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::SetProjectError(class [mscorlib]System.Exception)
  IL_00b3:  leave.s    IL_007f
  IL_00b5:  ldc.i4     0x800a0033
  .try IL_0000 to IL_0095 filter IL_0095 handler IL_00a9 to IL_00b5
  IL_00ba:  call       class [mscorlib]System.Exception [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::CreateProjectError(int32)
  IL_00bf:  throw
  IL_00c0:  ldloc.1
  IL_00c1:  brfalse.s  IL_00c8
  IL_00c3:  call       void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
  IL_00c8:  ret
} // end of method Program::Test

使用Reflector将此abberation反编译为:

代码语言:javascript
复制
public static void Test()
{
    int num2;
    try
    {
        int num3;
    Label_0000:
        num3 = 1;
        A();
    Label_0007:
        ProjectData.ClearProjectError();
        int num = 2;
    Label_000E:
        num3 = 3;
        B();
        goto Label_00C0;
    Label_001A:
        num3 = 5;
        C();
    Label_0021:
        num3 = 6;
        D();
    Label_0028:
        num3 = 7;
        ProjectData.ClearProjectError();
        if (num2 != 0)
        {
            goto Label_0047;
        }
        throw ProjectData.CreateProjectError(-2146828268);
    Label_003D:
        num3 = 9;
        E();
        goto Label_00C0;
    Label_0047:
        num2 = 0;
        switch ((num2 + 1))
        {
            case 1:
                goto Label_0000;

            case 2:
                goto Label_0007;

            case 3:
                goto Label_000E;

            case 4:
            case 10:
                goto Label_00C0;

            case 5:
                goto Label_001A;

            case 6:
                goto Label_0021;

            case 7:
                goto Label_0028;

            case 8:
            case 9:
                goto Label_003D;

            default:
                goto Label_00B5;
        }
    Label_007F:
        num2 = num3;
        switch (num)
        {
            case 0:
                goto Label_00B5;

            case 1:
                goto Label_0047;

            case 2:
                goto Label_0021;
        }
    }
    catch (object obj1) when (?)
    {
        ProjectData.SetProjectError((Exception) obj1);
        goto Label_007F;
    }
Label_00B5:
    throw ProjectData.CreateProjectError(-2146828237);
Label_00C0:
    if (num2 != 0)
    {
        ProjectData.ClearProjectError();
    }
}

除了它使用了一大堆开关和goto之外,我不知道这些代码实际上是做什么的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40061329

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档