ホームページ  >  記事  >  バックエンド開発  >  C#例外処理(Catch Throw)IL解析

C#例外処理(Catch Throw)IL解析

黄舟
黄舟オリジナル
2017-02-13 13:07:521318ブラウズ

1. キャッチスローのいくつかの形式とパフォーマンスへの影響:

 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コード(以下のコードはリリースバージョンのILコード):

.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

Form1_Click、Form1_Load、および Form1_Enter の try catch がコンパイラによって最適化されていることがわかります。修正された治療法: r

IL_0000:  ret         //即为  return  标记 返回值
E


处 Form1_doubleClick での Try Catch はパフォーマンスに影響します。


==》try catch を記述する 3 つの方法は、コードのリリース バージョンでまったく同じであり、パフォーマンスの消費を引き起こさないことがわかります。上記の結論を検証するためのテスト デモを作成できます (テスト済みで、結果は分析

と一致しています)。

それでは、デバッグモードのILコードはどのように見えるのでしょうか?


 .locals init ([0] class [mscorlib]System.Exception ee) //定义 Exception 类型参数 ee (此时已经把ee存入了Call Stack中)

デバッグ モードでの 4 つの書き込みメソッドの違いは、rethrow と throw の違いのみであることがわかります。イリノイ州で rethrow と throw は何を表しますか?

Throw: 現在計算スタック上にある例外オブジェクトをスローします。 C#例外処理(Catch Throw)IL解析

再スロー: 現在の例外を再スローします。


つまり、例外をスローすると、CLR は例外の開始点をリセットします。 CLR は、スローされた最新の例外の位置のみを記録します。次のコードは例外をスローし、CLR が例外の開始点をリセットします:

           try
            {

            }
            catch
            {
                throw;
            }
            try
            {

            }
            catch (Exception)
            {
                throw;
            }
            try
            {

            }
            catch (Exception ee)
            {
                throw;
            }

対照的に、例外オブジェクトをスローした場合、CLR はその例外の開始点をリセットしません。 stack を使用すると、次のコードは例外をスローしますが、CLR が例外の開始点をリセットすることはありません:


.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

C# は throw と throw ex を使用して例外をスローしますが、違いがあります。ふたつの間に。

C# で例外をスローするには throw; を使用することをお勧めします。これまでにキャッチした例外は処理されたと見なされますが、処理中に再度スローされます。 . 新しい例外が発生するため、エラーの実際の原因が見つからなくなります。

Throw e は例外を再スローします。これは元の例外を転送しませんが、StackTrace を含む多くの例外の内部情報を変更します。呼び出し接続が非常に深い状況では、パフォーマンスの低下は想像を超えます。

上記は C# 例外処理 (Catch Throw) IL 解析の内容です。その他の関連内容については、PHP 中国語 Web サイト (www.php.cn) をご覧ください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。