2016-10-15 2 views
2

Я всегда задавался вопросом: как печально известный оператор VB.NET «Включение ошибки снова» преобразуется в CIL? Включает ли он каждую линию с попыткой ... ловит?Выполнение CIL On Error Resume Next

ответ

3

Goto.

Вы не можете комбинировать try-catch с устаревшей обработкой ошибок одним способом. Когда вы используете On Error Resume Next, каждая строка кода в методе получает метку, а также уникальный идентификатор. В коде псевдо-C#:

int currentId = 0; 

Label1: 
currentId = 1; 
Line1(); 

Label2: 
currentId = 2; 
Line2(); 

Label3: 
currentId = 3; 
Line3(); 

Exit: 

Весь метод обернут в попытку поймать. Когда удастся исключение, обработчик catch проверит currentId и сделает простой goto на следующей метке в строке (и установлен ProjectError). В нашем случае, это будет выглядеть примерно так:

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, что в основном сводится к «заданию ошибки проекта и продолжению следующего утверждения».

0

Здесь вы идете:

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 

компилирует (без дополнительных методов):

.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 

Это неоднородности получают декомпилированы с отражателем на это:

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

Помимо факт, что он использует кучу переключателей и gotos, я понятия не имею, что на самом деле делает этот код.

Смежные вопросы