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

发布于 2024-07-30 04:48:17 字数 237 浏览 8 评论 0原文

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

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

Let's say you write an app in C#, VB, anything with .NET
When you hit build, does it really compile your code? I thought so until I started using redgates reflector on some of my assemblies and saw my code verbatim. I would have expected loops to be unrolled and another plethora of optimizations, instead nothing.

So when does the compilation actually happen? I think when it is built, code become IL (Intermediary Language) and when execution occurs, it is loading in the CLR? Is it optimized during CLR only and never at build time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

埋情葬爱 2024-08-06 04:48:17

当您在 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...依此类推...

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

When you compile in VS

  1. Your source code is compiled into a byte code known as the common intermediate language (CIL) or MSIL (Microsoft Intermediate Language).
  2. Metadata from every class and every methods (and every other thing :O) is included in the PE header of the resulting executable (be it a dll or an exe).
  3. If you're producing an executable the PE Header also includes a conventional bootstrapper which is in charge of loading the CLR (Common language runtime) when you execute you executable.

When you execute:

  1. The bootstraper initializes the CLR (mainly by loading the mscorlib assembly) and instructs it to execute your assembly.
  2. The CLR executes your main entry.
  3. Now, classes have a vector table which hold the addresses of the method functions, so that when you call MyMethod, this table is searched and then a corresponding call to the address is made. Upon start ALL entries for all tables have the address of the JIT compiler.
  4. When a call to one of such method is made, the JIT is invoked instead of the actual method and takes control. The JIT then compiles the CIL code into actual assembly code for the appropiate architecture.
  5. Once the code is compiled the JIT goes into the method vector table and replaces the address with the one of the compiled code, so that every subsequent call no longer invokes the JIT.
  6. Finally, the JIT handles the execution to the compiled code.
  7. If you call another method which haven't yet being compiled then go back to 4... and so on...

I post the answer here too as the other question was not really about this...

救赎№ 2024-08-06 04:48:17

它在编译时编译为 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;
    }
}

It is compiled down to IL at, well, compile time. Reflector's magic is that it "understands" the IL and converts it back into c# (or VB.NET or whatever. Look under the Options menu in Reflector and you can view the assembly in any format, including the IL).

In Reflector, you actually are not seeing your original code. You are seeing a translation of the IL into c#. Most of the time that will be very similar to what you wrote, but there are some telltale signs - for example, find a place where you implemented an auto-property:

string MyProperty {get;set;}

And you'll see what that actually compiles to, which is something like this:

public string MyProperty
{
    [CompilerGenerated]
    get
    {
        return this.<MyProperty>k__BackingField;
    }
    [CompilerGenerated]
    set
    {
        this.<MyProperty>k__BackingField = value;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文