I have the following code
using System;
class Pankaj
{
public static int Main()
{
int returnValue=0;
try
{
return returnValue;
throw new Exception();
}
catch(Exception ex){
return returnValue;
}
finally
{
returnValue++;
}
return returnValue;
}
}
THE MSIL generated of the above code is :
.method public hidebysig static int32 Main() cil managed
{
.entrypoint
// Code size 18 (0x12)
.maxstack 2
.locals init (int32 V_0,
int32 V_1)
IL_0000: ldc.i4.0
IL_0001: stloc.0
.try
{
.try
{
IL_0002: ldloc.0
IL_0003: stloc.1
IL_0004: leave.s IL_0010
} // end .try
catch [mscorlib]System.Exception
{
IL_0006: pop
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: leave.s IL_0010
} // end handler
} // end .try
finally
{
IL_000b: ldloc.0
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: stloc.0
IL_000f: endfinally
} // end handler
IL_0010: ldloc.1
IL_0011: ret
} // end of method Pankaj::Main
I have following questions:
The try statement defines the code block to run (to try). The catch statement defines a code block to handle any error. The finally statement defines a code block to run regardless of the result.
By using a finally block, you can clean up any resources that are allocated in a try block, and you can run code even if an exception occurs in the try block. Typically, the statements of a finally block run when control leaves a try statement.
In Java, such a desire is expressed with a try-finally clause. To use a try-finally clause: enclose in a try block the code that has multiple exit points, and. put in a finally block the code that must happen no matter how the try block is exited.
No, we cannot write any statements in between try, catch and finally blocks and these blocks form one unit.
Why the try catch is again included inside the try block.
Not sure on this one. It may just be the way that ildasm
chooses to decompile it. ECMA-335 says there are restrictions on how SEHClause
elements can be specified after a TryBlock
, but I haven't found those restrictions yet.
It looks like leave.s the last line in try and catch block is point to finally i.e. IL_0010 but at line IL_0010 its ldloc.1 which I believe means load local variable 1 on the stack, then how its pointing to finally block. Is it something like at location 1 we have address of finally block.
No, that's jumping to after the finally
block - to return the value, effectively. It doesn't help that you've got lots of return statements all returning the same thing, as well as unreachable code, but I believe the point is basically just to move the ret
outside the try
and catch
. I think the compiler is effectively setting up an extra local variable for the return value.
If I throw or return something from the catch block then how come the call statement falls to the finally block, it's already returned from the catch block but still the finally block gets executed.
That's how both C# and IL are defined - the finally
block will be executed however you exit the block.
Jon Skeet has already answered the last two questions, so I'll just focus on the first.
Why the try catch is again included inside the try block.
There are a couple of reasons for this:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With