Maison > Article > développement back-end > Gestion des exceptions C# (Catch Throw) Analyse IL
1. Plusieurs formes et impacts sur les performances du lancer attrapé :
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; } }
>IL correspondant code (le code suivant est le code IL de la version release) :
.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
Oui Voir que le try catch dans Form1_Click, Form1_Load et Form1_Enter a été optimisé par le compilateur :
IL_0000: ret //即为 return 标记 返回值
Seul le try catch dans Form1_DoubleClick est traité :
.locals init ([0] class [mscorlib]System.Exception ee) //定义 Exception 类型参数 ee (此时已经把ee存入了Call Stack中)
C'est-à-dire avoir un try catch dans Form1_doubleClick, cela affectera les performances.
try { } catch { throw; } try { } catch (Exception) { throw; } try { } catch (Exception ee) { throw; }
Vous pouvez écrire une démo de test pour vérifier la conclusion ci-dessus (testé, les résultats sont conforme à l'analyse ).
Alors à quoi ressemble le code IL en mode débogage ?
.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
On peut voir que la différence entre les quatre méthodes d'écriture en mode débogage n'est que : relancez et lancez la différence. Que signifient rethrow et throw en IL ?
Lancer : lance l'objet d'exception actuellement sur la pile de calcul.
Rethrow : Relance l'exception actuelle.
Autrement dit, lorsque nous lançons une exception, le CLR réinitialisera un point de départ d'exception. Le CLR enregistre uniquement l'emplacement de l'exception levée la plus récente. Le code suivant lève une exception, obligeant le CLR à réinitialiser le point de départ de l'exception :
try { //一些处理 } catch (Exception e) { //一些处理 throw e; //CLR认为这里是异常的起始点 }> Au contraire , si nous lançons un objet d'exception, le CLR ne réinitialisera pas le point de départ de sa pile. Le code suivant lève une exception, mais n'entraînera pas la réinitialisation du point de départ de l'exception par le CLR :
C# utilise throw et throw ex pour lancer des exceptions, mais il y a une différence entre les deux.
try { //一些处理 } catch (Exception e) { //一些处理 throw; //CLR不会重新设置异常的起始点 }
En C#, il est recommandé d'utiliser throw ; pour lancer des exceptions, throw ex effacera toutes les informations jusqu'à présent, en pensant que l'exception que vous avez détectée a été ; Il a été traité, mais une nouvelle exception a été levée pendant le traitement, de sorte que la véritable source de l'erreur n'a pas pu être trouvée.
throw e renvoie l'exception, qui ne transmet pas l'exception d'origine, mais modifie de nombreuses informations internes sur l'exception, y compris StackTrace pour le cas d'une connexion d'appel profonde, perte de performances au-delà de l'imagination ; .
Ce qui précède est le contenu de l'analyse IL de gestion des exceptions C# (Catch Throw) Pour plus de contenu connexe, veuillez prêter attention au site Web PHP chinois (www.php.cn). )!