编译器魔术:为什么?

时间:2009-11-03 21:31:33

标签: c# optimization compiler-construction

我注意到以下代码:

if (x.ID > 0 && !x.IsCool)

Microsoft C#3.0(VS2008 SP1)编译器将对其进行优化:

if (!((x.Id <= 0) || x. IsCool))

这是在Debug build 上启用了优化。为什么编译器会这样做?它在执行方面更快吗?

我用Reflector找到了(我实际上是在寻找不同的东西)

3 个答案:

答案 0 :(得分:49)

C#编译器当然不会为您的代码段生成等效的C#代码。它编译成IL。基本上,您所看到的(来自Reflector,我猜)是反编译器为该IL吐出的等效C#代码。

  1. 语言规范没有说明“未经优化”的代码是什么。允许C#编译器生成任何有效的,功能相同的代码。即使没有优化开关,编译器也可以进行基本优化。除此之外,你不能说编译器的自然 编译器是否故意优化它

    < / LI>
  2. 整个if语句根据“and”子句中指定的每个单独表达式的值计算为一系列条件分支。表达式是 not 在单个代码块中使用“和”指令进行求值。反编译器的输出是从这些分支推断出来的。反编译器不能总是推断你写的原始表达式。它只输出相当的东西。

  3. 同样,这个片段之间的区别是:

    if (a) { something(); }
    else { somethingElse(); }
    

    和此代码段:

    if (!a) { somethingElse(); }
    else { something(); }
    

    不是通过查看已编译的代码来区分的。

答案 1 :(得分:8)

我认为从语义语义的角度来看,这两个表达式完全相同。两种方式都涉及短路。

我有点惊讶的是,安德鲁的答案已经有十个赞成票;这对我来说听起来像是胡说八道,但也许我真的错过了一些微妙的东西。

修改

总结一下:

OP的问题是“为什么会发生这种优化”。

事实上,没有'优化'的发生。两个C#源代码在逻辑上是等价的。 “.Net Reflector”或其他任何反汇编工具也许可能将同一个IL反编译成一个或另一个。在IL级别,只有一堆条件跳转,所以没有必要知道“哪种方式是哪种方式,哪种方式是其他方式”或其他类似的DeMorgan等价方式。

令人着迷的是,人们非常乐意对这个问题的答案进行评论,即使(或者可能是因为)原始问题没有多大意义(或依赖于错误的假设)。

令人高兴的是,最​​终人群的智慧(以及像@Mehrdad这样聪明的人)占上风。欢迎使用StackOverflow!

(我正在回答一个wiki,因为当代表应该被授予“问题的好答案”时,我不希望代表“讲述一个问题的故事”。但我认为这个问题的故事很有趣。)

答案 2 :(得分:6)

if编译为条件跳转操作码。从表达式中提取否定允许通过使用直通块交换条件跳转目标来优化它。

相关问题