8

假设你用 C#、VB 和 .NET 编写了一个应用程序。当你点击构建时,它真的编译了你的代码吗?我是这么认为的,直到我开始在我的一些程序集中使用 redgates 反射器并逐字查看我的代码。我本来希望循环展开并进行其他过多的优化,而不是什么都没有。

那么编译实际发生在什么时候呢?我认为当它被构建时,代码变成 IL(中间语言)并且当执行发生时,它正在加载到 CLR 中?它是否仅在 CLR 期间进行优化,而不是在构建时进行优化?

4

2 回答 2

24

当你在 VS 中编译时

  1. 您的源代码被编译成称为通用中间语言 (CIL) 或 MSIL(Microsoft 中间语言)的字节码。
  2. 来自每个类和每个方法(以及所有其他事物:O)的元数据都包含在生成的可执行文件(无论是 dll 还是 exe)的 PE 头中。
  3. 如果您正在生成可执行文件,PE Header 还包括一个传统的引导程序,该引导程序负责在您执行可执行文件时加载 CLR(公共语言运行时)。

当你执行:

  1. 引导程序初始化 CLR(主要通过加载 mscorlib 程序集)并指示它执行您的程序集。
  2. CLR 执行您的主条目。
  3. 现在,类有一个向量表,其中保存了方法函数的地址,因此当您调用 MyMethod 时,会搜索该表,然后对该地址进行相应的调用。在开始时,所有表的所有条目都具有 JIT 编译器的地址。
  4. 当调用此类方法之一时,将调用 JIT 而不是实际方法并获得控制权。然后,JIT 将 CIL 代码编译为适合架构的实际汇编代码。
  5. 一旦代码被编译,JIT 就会进入方法向量表,并用编译后的代码替换地址,这样每个后续调用都不再调用 JIT。
  6. 最后,JIT 处理编译代码的执行。
  7. 如果您调用另一个尚未编译的方法,则返回 4... 等等...

我也在这里发布答案,因为另一个问题与此无关......

于 2009-08-05T22:56:38.740 回答
4

它在编译时被编译为 IL。Reflector 的魔力在于它“理解”IL 并将其转换回 c#(或 VB.NET 或其他任何东西。在 Reflector 的“选项”菜单下查看,您可以查看任何格式的程序集,包括 IL)。

在 Reflector 中,您实际上并没有看到您的原始代码。您正在看到将 IL 翻译成 c#。大多数情况下,这与您编写的内容非常相似,但有一些明显的迹象 - 例如,找到您实现自动属性的地方:

string MyProperty {get;set;}

你会看到它实际编译成什么,是这样的:

public string MyProperty
{
    [CompilerGenerated]
    get
    {
        return this.<MyProperty>k__BackingField;
    }
    [CompilerGenerated]
    set
    {
        this.<MyProperty>k__BackingField = value;
    }
}
于 2009-08-05T22:56:03.407 回答