.NET如何以及何时实际编译代码?

时间:2009-08-05 22:53:41

标签: .net clr intermediate-language

假设您使用.NET编写了一个用C#,VB编写的应用程序 当你点击构建时,它真的编译你的代码吗?我一直这么想,直到我开始在我的一些装配上使用redgates反射器并逐字地看到我的代码。我本来期望循环被展开和另外多次优化,而不是什么。

那么编译何时实际发生?我认为当它构建时,代码变成IL(中介语言),并且当执行时,它正在加载到CLR中?它是仅在CLR期间进行优化而从未在构建时进行优化的吗?

2 个答案:

答案 0 :(得分:22)

在VS中编译时

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

    1. bootstraper初始化CLR(主要通过加载mscorlib程序集)并指示它执行程序集。
    2. CLR执行您的主条目。
    3. 现在,类有一个向量表,其中包含方法函数的地址,因此当您调用MyMethod时,将搜索此表,然后对该地址进行相应的调用。启动后,所有表的所有条目都具有JIT编译器的地址。
    4. 当调用其中一个方法时,调用JIT而不是实际方法并控制。然后,JIT将CIL代码编译为适当架构的实际汇编代码。
    5. 编译代码后,JIT进入方法向量表并将地址替换为其中一个已编译的代码,以便每个后续调用不再调用JIT。
    6. 最后,JIT处理已编译代码的执行。
    7. 如果您调用另一个尚未编译的方法,请返回4 ...依此类推......
    8. 我也在这里发布答案,因为另一个问题并不是真的这个......

答案 1 :(得分:4)

在编译时编译到IL。 Reflector的神奇之处在于它“理解”IL并将其转换回c#(或VB.NET或其他任何内容。在Reflector的Options菜单下查看,您可以以任何格式查看程序集,包括IL)。

在Reflector中,您实际上没有看到原始代码。您正在看到IL转换为c#。大部分时间与您所写的内容非常相似,但有一些明显的迹象 - 例如,找到您实施auto-property的地方:

string MyProperty {get;set;}

你会看到实际编译的内容,就像这样:

public string MyProperty
{
    [CompilerGenerated]
    get
    {
        return this.<MyProperty>k__BackingField;
    }
    [CompilerGenerated]
    set
    {
        this.<MyProperty>k__BackingField = value;
    }
}