1. Several forms and performance effects of Catch throw:
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; } }
the corresponding IL code (the following code is the release version of the Il Code):
. method private Hidebysig instance void Form1_Click (object sender, cl [Mscorlib]system.eventargs E] CIL managed{//code size 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{//code size 1 (0x1). Maxstack 8 Il_0000:ret}//End of M Ethod Form1::form1_load.method private Hidebysig instance void Form1_enter (object sender, class [Mscorlib]system.eventargs E) CIL managed{//code size 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{//code size 1 (0x1). Ma Xstack 1. Locals init([0] class [mscorlib]system.exception ee) Il_0000:ret}//End of method Form1::form1_doubleclick
you can see that the try catch in Form1_Click, Form1_Load, and Form1_enter has been optimized by the compiler:
il_0000: ret //Returns a value for return token
Try catch is only handled in Try catch in Form1_doubleclick:
. Locals init ([0] class [mscorlib]system.exception ee)//define Exception type parameter EE (this time the EE has been deposited in the call stack)
that is, try catch in Form1_doubleclick will have an impact on performance.
= = "You can see that the three try catch notation is exactly the same for the release version of code and does not incur any performance costs:
Try { } catch { throw; } Try { } catch (Exception) { throw; } Try { } catch (Exception ee) { throw; }
for the above conclusions, you can write the test demo (tested, the results are consistent with the analysis).
So what does the IL code look like in debug mode?
. method private Hidebysig instance void Form1_Click (object sender, cl [Mscorlib]system.eventargs E] CIL managed{//code size one (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, Clas s [Mscorlib]system.eventargs e) CIL managed{//code size one (0XB). maxstack 1 Il_0000:nop. try {il_0001:no P 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.eve Ntargs e) CIL managed{//code size one (0XB). Maxstack 1. Locals init ([0] class [mscorlib]system.exception ee) il_0 000:nop. try {il_0001:nop Il_0002:nop il_0003:leave.s il_0009}//end. Try Catch [Mscorlib]syst Em. 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{//code size one (0XB). m Axstack 1. Locals init ([0] class [mscorlib]system.exception ee) il_0000:nop. try {il_0001:nop il_0002:n OP 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
It can be seen that four ways of writing in debug mode differ only: the difference between rethrow and throw. What does rethrow and throw in Il stand for?
Throw: Throws the exception object that is currently on the evaluation stack.
Rethrow: Throws the current exception again.
that is, when we throw an exception, the CLR will reset an exception starting point. The CLR only records where the last exception was thrown. The following code throws an exception that causes the CLR to reset the starting point of the exception:
Try { //some processing } catch (Exception e) { //Some handle throw e; The CLR thinks this is the starting point for the exception }
Conversely, if we throw an exception object, the CLR will not reset its stack's starting point, and the following code throws an exception, but does not cause the CLR to reset the starting point of the exception:
Try { //some processing } catch (Exception e) { //some handle throw; The CLR does not reset the starting point of the exception }
exceptions are thrown in C # using throw and throw ex, but they are different.
It is recommended to use throw in C #, throw an exception, throw ex; all the information so far is emptied, and the exception that you catch is handled, but a new exception is thrown in the process and no real source of error is found.
Throw e re-throws the exception, not forwarding the original exception, but changes many of the exception's internal information, including StackTrace, and the performance loss is beyond imagination for a deep case of a call.
Expand reading:
Il command details
. NET exception handling Best Practices (translated)
C # exception handling (Catch Throw) IL analysis