2016-10-15 47 views

回答

3

轉到。

您無法將try-catch與傳統錯誤處理結合在一個方法中。當您使用On Error Resume Next時,方法中的每一行代碼都會得到一個標籤以及一個唯一標識符。在僞C#代碼中:

int currentId = 0; 

Label1: 
currentId = 1; 
Line1(); 

Label2: 
currentId = 2; 
Line2(); 

Label3: 
currentId = 3; 
Line3(); 

Exit: 

整個方法被包裝在try 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 

這abberation獲取與反射反編譯如下:

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,我不知道該代碼實際上做了什麼。