Maison  >  Article  >  développement back-end  >  Gestion des exceptions C# (Catch Throw) Analyse IL

Gestion des exceptions C# (Catch Throw) Analyse IL

黄舟
黄舟original
2017-02-13 13:07:521317parcourir

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.

==" On constate que les trois façons d'écrire try catch sont exactement les mêmes pour la version release du code, et n'entraîneront aucune consommation de 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 ). Gestion des exceptions C# (Catch Throw) Analyse IL


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). )!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn