Heim >Backend-Entwicklung >C#.Net-Tutorial >C#-Ausnahmebehandlung (Catch Throw) IL-Analyse
1. Verschiedene Formen und Leistungsauswirkungen des Fangwurfs:
private void Form1_Click(object sender, EventArgs e) { try { } catch { throw; } } private void Form1_Load(object sender, EventArgs e) { try { } catch (Exception) { throw; } } private void Form1_Enter(object sender, EventArgs e) { try { } catch (Exception ee) { throw; } } private void Form1_DoubleClick(object sender, EventArgs e) { try { } catch (Exception ee) { throw ee; } }
>Entsprechende IL Code (der folgende Code ist der IL-Code der Release-Version):
.method private hidebysig instance void Form1_Click(object sender, class [mscorlib]System.EventArgs e) cil managed { // 代码大小 1 (0x1) .maxstack 8 IL_0000: ret } // end of method Form1::Form1_Click .method private hidebysig instance void Form1_Load(object sender, class [mscorlib]System.EventArgs e) cil managed { // 代码大小 1 (0x1) .maxstack 8 IL_0000: ret } // end of method Form1::Form1_Load .method private hidebysig instance void Form1_Enter(object sender, class [mscorlib]System.EventArgs e) cil managed { // 代码大小 1 (0x1) .maxstack 8 IL_0000: ret } // end of method Form1::Form1_Enter .method private hidebysig instance void Form1_DoubleClick(object sender, class [mscorlib]System.EventArgs e) cil managed { // 代码大小 1 (0x1) .maxstack 1 .locals init ([0] class [mscorlib]System.Exception ee) IL_0000: ret } // end of method Form1::Form1_DoubleClick
Ja, siehe dass der Try-Catch in Form1_Click, Form1_Load und Form1_Enter vom Compiler optimiert wurde:
IL_0000: ret //即为 return 标记 返回值
Nur der Try-Catch in Form1_DoubleClick wird verarbeitet:
.locals init ([0] class [mscorlib]System.Exception ee) //定义 Exception 类型参数 ee (此时已经把ee存入了Call Stack中)
Der Versuch, „catch“ in Form1_doubleClick zu verwenden, beeinträchtigt die Leistung.
try { } catch { throw; } try { } catch (Exception) { throw; } try { } catch (Exception ee) { throw; }
Sie können eine Testdemo schreiben, um die obige Schlussfolgerung zu überprüfen (getestet, die Ergebnisse sind im Einklang mit der Analyse ).
Wie sieht also der IL-Code im Debug-Modus aus?
.method private hidebysig instance void Form1_Click(object sender, class [mscorlib]System.EventArgs e) cil managed { // 代码大小 11 (0xb) .maxstack 1 IL_0000: nop .try { IL_0001: nop IL_0002: nop IL_0003: leave.s IL_0009 } // end .try catch [mscorlib]System.Object { IL_0005: pop IL_0006: nop IL_0007: rethrow } // end handler IL_0009: nop IL_000a: ret } // end of method Form1::Form1_Click .method private hidebysig instance void Form1_Load(object sender, class [mscorlib]System.EventArgs e) cil managed { // 代码大小 11 (0xb) .maxstack 1 IL_0000: nop .try { IL_0001: nop IL_0002: nop IL_0003: leave.s IL_0009 } // end .try catch [mscorlib]System.Exception { IL_0005: pop IL_0006: nop IL_0007: rethrow } // end handler IL_0009: nop IL_000a: ret } // end of method Form1::Form1_Load .method private hidebysig instance void Form1_Enter(object sender, class [mscorlib]System.EventArgs e) cil managed { // 代码大小 11 (0xb) .maxstack 1 .locals init ([0] class [mscorlib]System.Exception ee) IL_0000: nop .try { IL_0001: nop IL_0002: nop IL_0003: leave.s IL_0009 } // end .try catch [mscorlib]System.Exception { IL_0005: stloc.0 IL_0006: nop IL_0007: rethrow } // end handler IL_0009: nop IL_000a: ret } // end of method Form1::Form1_Enter .method private hidebysig instance void Form1_DoubleClick(object sender, class [mscorlib]System.EventArgs e) cil managed { // 代码大小 11 (0xb) .maxstack 1 .locals init ([0] class [mscorlib]System.Exception ee) IL_0000: nop .try { IL_0001: nop IL_0002: nop IL_0003: leave.s IL_0009 } // end .try catch [mscorlib]System.Exception { IL_0005: stloc.0 IL_0006: nop IL_0007: ldloc.0 IL_0008: throw } // end handler IL_0009: nop IL_000a: ret } // end of method Form1::Form1_DoubleClick
Es ist ersichtlich, dass der Unterschied zwischen den vier Schreibmethoden im Debug-Modus nur beträgt : erneut werfen und die Differenz werfen. Wofür stehen Rethrow und Throw in IL?
Auslösen: Wirft das derzeit auf dem Berechnungsstapel befindliche Ausnahmeobjekt aus.
Erneut auslösen: Die aktuelle Ausnahme erneut auslösen.
Das heißt, wenn wir eine Ausnahme auslösen, setzt die CLR einen Ausnahmestartpunkt zurück. Die CLR zeichnet nur den Ort der zuletzt ausgelösten Ausnahme auf. Der folgende Code löst eine Ausnahme aus, wodurch die CLR den Startpunkt der Ausnahme zurücksetzt:
try { //一些处理 } catch (Exception e) { //一些处理 throw e; //CLR认为这里是异常的起始点 }> Im Gegenteil Wenn wir ein Ausnahmeobjekt auslösen, setzt die CLR den Startpunkt ihres Stapels nicht zurück. Der folgende Code löst eine Ausnahme aus, führt jedoch nicht dazu, dass die CLR den Startpunkt der Ausnahme zurücksetzt:
try { //一些处理 } catch (Exception e) { //一些处理 throw; //CLR不会重新设置异常的起始点 }C# verwendet throw und throw ex, um Ausnahmen auszulösen, aber es gibt einen Unterschied zwischen den beiden.
Es wird empfohlen, throw ex zu verwenden, um bisher alle Informationen zu löschen Es wurde verarbeitet, aber während der Verarbeitung wurde eine neue Ausnahme ausgelöst, sodass die eigentliche Fehlerquelle nicht gefunden werden konnte.
throw e löst die Ausnahme erneut aus, wodurch die ursprüngliche Ausnahme nicht weitergeleitet wird, aber viele Ausnahme-interne Informationen geändert werden, einschließlich StackTrace für den Fall einer tiefen Anrufverbindung, Leistungsverlust Unvorstellbar .
Das Obige ist der Inhalt der C#-Ausnahmebehandlung (Catch Throw) IL-Analyse. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn). )!