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

问题描述 投票:0回答:2

假设您使用 C#、VB.NET 或任何使用 .NET 的语言编写应用程序。 当你点击构建时,它真的会编译你的代码吗?我是这么认为的,直到我开始在我的一些程序集上使用 Redgate 的反射器并逐字查看我的代码。我本来希望展开循环并进行大量优化,但什么也没有。

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

.net clr intermediate-language
2个回答
25
投票

当你在VS中编译时

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

执行时:

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

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


4
投票

它在编译时编译为 IL。 Reflector 的神奇之处在于它“理解”IL 并将其转换回 c#(或 VB.NET 或其他语言。查看 Reflector 中的“选项”菜单,您可以查看任何格式的程序集,包括 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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.