Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Compiler Optimization - Catch only containing throw

I would expect the following two implementations of MyMethod to behave exactly the same. Do they? If not, this could already be my wrong assumption:

First:

public int MyMethod(int x)
{
    try
    {
        return x + 8;
    }
    catch
    {
        throw;
    }
}

Second:

public int MyMethod(int x)
{
    return x + 8;
}

So, I would assume the compiler will optimize this out, i.e. remove the unnecessary try/catch block of the first implementation (when in Release Mode). As it turns out, it doesn't - here is the generated IL for the two code samples:

First:

.method public hidebysig instance int32  MyMethod(int32 x) cil managed
{
  // Code size       11 (0xb)
  .maxstack  2
  .locals init ([0] int32 CS$1$0000)
  .try
  {
    IL_0000:  ldarg.1
    IL_0001:  ldc.i4.8
    IL_0002:  add
    IL_0003:  stloc.0
    IL_0004:  leave.s    IL_0009
  }  // end .try
  catch [mscorlib]System.Object 
  {
    IL_0006:  pop
    IL_0007:  rethrow
  }  // end handler
  IL_0009:  ldloc.0
  IL_000a:  ret
} // end of method MyClass::MyMethod

Second:

.method public hidebysig instance int32  MyMethod(int32 x) cil managed
{
  // Code size       4 (0x4)
  .maxstack  8
  IL_0000:  ldarg.1
  IL_0001:  ldc.i4.8
  IL_0002:  add
  IL_0003:  ret
} // end of method MyClass::MyMethod

Could someone please shed some light on this? Is there a relevant difference in behaviour of the two implementations (side effects?)? Could the compiler optimize the code, but just doesn't? Thanks!

like image 799
Dennis Avatar asked Feb 27 '26 07:02

Dennis


1 Answers

Most optimization is done by the JITter and only some optimization by the compiler generating the IL. So I couldn't tell what actually is compiled to machine code during the run of the program (you could possibly debug though).
You can find information in the post: http://blogs.msdn.com/b/ericlippert/archive/2009/06/11/what-does-the-optimize-switch-do.aspx written by one of the c# compiler team.
There it says:
"The /optimize flag does not change a huge amount of our emitting and generation logic. We try to always generate straightforward, verifiable code and then rely upon the jitter to do the heavy lifting of optimizations when it generates the real machine code"

You can also find information at the link on some cases that are actually optimized for generating IL code.

Update

There is a performance test on the implications in the answer of:
what will empty catch and throw block do?
it confirms that it is not optimized away.

And to the question if the code could be removed there was a discussion at: Can I remove empty catch with throw?

like image 128
Uwe Hafner Avatar answered Mar 01 '26 20:03

Uwe Hafner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!