10

我对MSIL托管代码感到困惑,它们是相同的还是不同的?我的意思是说,当我们构建 C# 代码时会发生什么?

哪一个是对的

C# Code → C# compiler → Managed Code → MSIL

或者

C# Code → C# compiler → MSIL

请提供真实的参考或链接以支持您的答案。

4

5 回答 5

13

你混淆了不同的东西。托管代码是用托管语言(C#、VB.NET、F# 和许多其他语言)编写的代码,这些语言编译成 CIL(通用中间语言,以前称为 Microsoft 中间语言或 MSIL)并在 CLR 的托管环境中运行。

另一方面,非托管代码直接编译为本机代码(也称为程序集),它不在 CLR 上运行。

当您构建 C# 代码时,它会被编译成 CIL。这就是为什么您可以使用 ildasm 或 Reflector 之类的工具来检查编译后的代码的原因。执行 CIL 代码时究竟会发生什么取决于具体情况。它可能是

  1. 使用 JIT 编译器(最常见的选项)“及时”编译为本机代码。
  2. 使用预编译的本机代码执行(您可以使用 NGEN 来获取)。
  3. 直接解释;我认为某些版本的 .Net for Windows CE 或类似版本可以做到这一点。
于 2012-04-24T12:13:50.017 回答
11

如评论中所述,MSIL 已重命名为 CIL。

C# Code --> C# compiler --> CIL

因为

CIL = Managed

当放在它的上下文中时,还有

Native Code = Unmanaged

请注意,这Managed Code是完全不同的东西,它指的是源代码


如果你想扩展它,那么更正的完整过程是:

.NET Code --Compiler--> CIL (Managed) --JIT/NGEN--> Native Code (Unmanaged)


参考:

  1. 介绍 C#(什么是 .NET Framework?-> CIL 和 JIT -> 前两句)

  2. JIT / NGEN(迈向托管代码的成本模型 -> 即时编译器 -> 整体)

于 2012-04-24T11:44:35.767 回答
3

编写为在 CLR 的控制下运行的代码称为托管代码。(来源)。所以

C#代码→C#编译器→CIL(以前称为MSIL)

是正确的。

于 2012-04-24T11:49:11.707 回答
2

我不会在这里详细介绍,因为其他人已经介绍了很多,但我想澄清一些其他答案没有真正解释好或正确的观点。这在很大程度上是迂腐的,对于 99.99999% 的情况,您可以只想到“C# 和 CIL/MSIL 是托管代码”,但这有一些微妙之处。

首先,CIL/MSIL 被称为“中间语言”,这意味着它是一种计算机语言,用作源代码和最终本机机器代码之间的中间步骤。然而,这不一定是这种情况。我听说过实验项目,他们创建了一个直接执行 CIL(或称为 Java 字节码的 java 等效项)的 CPU,而无需先将其转换为本机形式(基本上,CIL 是本机形式)。

托管代码是指由某种托管运行时“管理”的代码。这通常意味着代码被垃圾收集,并且具有某种安全层来防止诸如缓冲区溢出和本机代码中可能发生的其他类型的问题。在 .net 中,这称为公共语言运行时 (CLR)

在过去,这曾经被称为“虚拟机”,以及为什么将 java 环境称为 JVM,尽管该术语现在在很大程度上是用词不当。如今,使用 JIT(即时)编译器,没有真正的“虚拟机”,而是一层“包装”本机编译代码的代码,以确保您不会违反规则,并在之后进行清理你的代码。它还抽象出一些特定于平台的东西,这样 CIL 就不必担心它们。

因此,托管代码是指在托管运行时中运行的代码的概念。当 CIL 在运行时(例如 .NET 运行时环境)中运行时,它被视为托管代码。

C# 和 VB.NET 通常被认为是“托管语言”,因为它们通常编译为 CIL 并在托管运行时下运行。然而,这并不一定是这样(尽管如果遵循规范的字母,它可能确实是这样)。例如,有些编译器可以将 c# 直接编译为本机代码而无需中间层,而 C# 的运行时解释器根本不编译代码,而是在运行时“解释”它。

所以要点是托管代码和 CIL 是两个不同的东西,但它们是相关的。

于 2013-04-20T19:28:37.130 回答
2

当您为 Windows 编写程序时,您可以编写两种类型的代码之一:托管代码和本机代码。本机代码直接编译成机器可执行文件或 .dll,而托管代码是针对 .NET 运行时的代码(换句话说,它的编译形式,称为程序集,是包含 CIL 指令的文件)。在运行时,CIL 由 JIT 编译器转换为机器码并执行。托管和本机之间的区别与语言(及其编译器)的目标有关。本机代码以机器本身为目标,因为它被编译成一组直接机器指令。另一方面,C# 编译器将您的代码编译成 CIL,因为 C# 语言编译器以 .NET 运行时为目标。然后可以说 C# 是一种“托管语言”,而用它编写的任何代码都是“托管代码”。例如:

C src  -> gcc.exe -> .exe containing a machine binary ->            processor
C# src -> csc.exe -> .exe assembly containing CIL     -> CLR/JIT -> processor

我认为使用“托管”一词的原因是因为形成代码的指令最终由 .NET 运行时处理,而不是由处理器直接执行。将源代码编译为 CIL 的额外步骤本身并不是使您的代码受到管理的原因:相反,您的程序永远不会被处理器直接执行这一事实。CIL 正是允许多种不同的托管语言针对同一运行时的原因。

我知道这比仅仅说“托管语言编译成 CIL”要冗长得多,但那是因为我真的不认为这是对什么使代码托管的完全准确的描述。Java 字节码类似于 CIL,但存在可以本地执行字节码的实际“Java 处理器”。.NET CIL 也可以使用这样的处理器,这意味着编译成 CIL 并在这样的机器上运行的代码将成为本机代码。您的代码必须通过 CLR 处理这一事实使其得以管理。CIL 恰好是代码必须转换为运行时才能执行它的格式。

于 2013-04-20T17:55:19.240 回答