집 >백엔드 개발 >C#.Net 튜토리얼 >C# 예외 처리(Catch Throw) IL 분석
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; }
위의 결론을 확인하기 위해 테스트 데모를 작성할 수 있습니다(테스트 결과는 다음과 일치함). 분석).
디버그 모드의 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)를 참고해주세요. )!