我希望以下两个MyMethod
的实现行为完全相同。他们呢?如果没有,这可能是我错误的假设:
首先:
public int MyMethod(int x)
{
try
{
return x + 8;
}
catch
{
throw;
}
}
第二
public int MyMethod(int x)
{
return x + 8;
}
所以,我认为编译器会优化它,即删除第一个实现的不必要的try / catch块(当处于释放模式时)。 事实证明,它没有 - 这是两个代码样本生成的IL:
首先:
.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
第二
.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
有人可以对此有所了解吗?这两种实现的行为是否存在相关差异(副作用?)?编译器可以优化代码,但不是吗?谢谢!
答案 0 :(得分:2)
大多数优化都是由JITter完成的,只有编译器生成IL才进行一些优化。所以我无法分辨在程序运行期间实际编译成机器代码的是什么(尽管你可以调试)
您可以在帖子中找到信息:http://blogs.msdn.com/b/ericlippert/archive/2009/06/11/what-does-the-optimize-switch-do.aspx由一个c#编译器团队编写
它说:
“/ optimize标志不会改变我们的大量发射和生成逻辑。我们总是尝试生成简单,可验证的代码,然后依靠抖动在生成真实机器代码时进行大量优化”
您还可以在链接上找到有关为生成IL代码而实际优化的一些案例的信息。
更新
对答案的含义进行了性能测试:
what will empty catch and throw block do?
它证实它没有被优化掉。
关于是否可以删除代码的问题,有一个讨论: Can I remove empty catch with throw?
答案 1 :(得分:0)
编译器不能假设在这种情况下不需要try / catch块。
如果里面有任何代码,则可能会抛出异常。 例如:
即使你不是"处理"在" catch"中捕获的异常对象声明,很多事情都发生在后台。例如,启动Exception对象的构造函数(编译器无法确定是否存在重要的实现)。
正如你所看到的那样,从编译器的角度来看,即使是单个(几乎是空的)try / catch块也不是那么简单。