Heim  >  Artikel  >  Backend-Entwicklung  >  C#-Ausnahmebehandlung (Catch Throw) IL-Analyse

C#-Ausnahmebehandlung (Catch Throw) IL-Analyse

黄舟
黄舟Original
2017-02-13 13:07:521278Durchsuche

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.

==" Es ist ersichtlich, dass die drei Schreibweisen von Try Catch für die Release-Version des Codes genau gleich sind und keinen Leistungsverbrauch verursachen:

           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 ). C#-Ausnahmebehandlung (Catch Throw) IL-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). )!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn