>  기사  >  백엔드 개발  >  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가 컴파일러에 의해 최적화되었습니다.


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


 Form1_DoubleClick의 try catch만 처리됩니다.

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

즉, Form1_DoubleClick의 try catch가 성능에 영향을 미치게 됩니다.

==" try catch를 작성하는 세 가지 방법은 릴리스 버전의 코드에서 완전히 동일하며 성능 소모를 유발하지 않는다는 것을 알 수 있습니다.

           try
            {

            }
            catch
            {
                throw;
            }
            try
            {

            }
            catch (Exception)
            {
                throw;
            }
            try
            {

            }
            catch (Exception ee)
            {
                throw;
            }

위의 결론을 확인하기 위해 테스트 데모를 작성할 수 있습니다(테스트 결과는 다음과 일치함). 분석C# 예외 처리(Catch Throw) IL 분석).


디버그 모드의 IL 코드는 어떤 모습일까요?

.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

디버그 모드에서 네 가지 쓰기 방법의 차이점은 다음과 같습니다. 다시 던지는 것과 던지는 것의 차이. IL에서 rethrow와 throw는 무엇을 의미합니까?


Throw: 현재 계산 스택에 있는 예외 개체를 throw합니다.
Rethrow: 현재 예외를 다시 발생시킵니다.

즉, 예외가 발생하면 CLR은 예외 시작 지점을 재설정합니다. CLR은 가장 최근에 발생한 예외의 위치만 기록합니다. 다음 코드는 예외를 발생시켜 CLR이 예외의 시작점을 재설정하도록 합니다. 예외 개체를 발생시키는 경우 CLR은 해당 스택의 시작점을 재설정하지 않습니다. 다음 코드는 예외를 발생시키지만 발생시키지는 않습니다. CLR은 예외의 시작점을 재설정합니다.

            try
            {
                //一些处理
            }
            catch (Exception e)
            {
                //一些处理
                throw e;   //CLR认为这里是异常的起始点
            }

C#은 throw 및 throw ex를 사용하여 throw합니다. 예외는 있지만 둘 사이에는 차이가 있습니다.

C#에서는 throw를 사용하여 예외를 처리하는 것이 좋습니다. 처리가 되었는데, 처리 중에 새로운 예외가 발생하여 실제 오류 원인을 찾을 수 없었습니다.

throw e는 예외를 다시 발생시킵니다. 이는 원래 예외를 전달하지 않지만 깊은 호출 연결을 위한 StackTrace를 포함한 많은 예외 내부 정보를 변경하며 상상을 초월하는 성능 손실을 발생시킵니다.

위는 C# 예외 처리(Catch Throw) IL 분석 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요. )!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.