82

关于这一点有很多相互矛盾的信息。虽然有人说 C# 是编译的(因为它被编译成 IL,然后在运行时编译成本机代码),但其他人说它被解释为它需要 .NET。EN 维基 说:

许多解释语言首先被编译成某种形式的虚拟机代码,然后在运行时被解释或编译为本机代码。

所以我很困惑。谁能解释清楚?

4

13 回答 13

81

C# 由 c# 编译器编译成 IL。

然后根据需要将此 IL 即时编译 (JIT) 成主机的本机汇编语言。不过,可以编写一个解释 IL 的 .NET 运行时。即使这样做了,我仍然认为 c# 是一种编译语言。

于 2012-01-12T15:13:53.937 回答
47

纯编译语言有一些优点。速度,通常,通常是工作集大小。纯解释型语言有一些优点。不需要显式编译阶段的灵活性,允许我们就地编辑,并且通常更容易移植。

在这种情况下,jitted 语言适合中间立场。

这就是为什么我们可能将 jitted 语言视为编译或解释的原因,这取决于我们关心达到哪个指标的哪个位置,以及我们对一个或另一个的偏见。

C# 也可以在第一次运行时编译,就像在 ASP.NET 中发生的那样,这使得它在这种情况下接近解释(尽管在这种情况下它仍然被编译为 IL 然后被 jitted)。当然,在这种情况下,它几乎具有解释的所有优点(与经典 ASP 中使用的 VBScript 或 JScript 相比),以及编译的许多优点。

严格来说,没有一种语言是 jitted、interpreted 或compiled qua 语言。我们可以将 NGen C# 转换为本机代码(尽管如果它执行诸如动态加载程序集之类的操作,它仍将使用 IL 和 jitting)。我们可以为 C 或 C++ 编写一个解释器(有几个人已经这样做了)。不过,在其最常见的用例中,C# 被编译为 IL,然后进行 jitted,这既不是解释的经典定义,也不是编译的经典定义。

于 2012-01-12T15:42:47.983 回答
20

基于意见的语义和陈述太多。

首先:C# 不是解释型语言;CLR 和 JVM 被认为是“运行时”或“中间件”,但同样的名称也适用于 Perl 之类的东西。这在关心名字的人中造成了很多混乱。

引用运行时的术语“解释器”通常意味着现有代码解释一些非本地代码。有两大范式:解析读取原始源代码并采取逻辑动作;字节码执行首先将代码编译为非本地二进制表示,这需要更少的 CPU 周期来解释。

Java 最初编译成字节码,然后经过解释器;现在,JVM 读取字节码并及时将其编译为本机代码。CIL 也是如此:CLR 使用即时编译来编译本机代码。

考虑运行源代码、运行字节码、编译为本机、即时编译、通过编译器运行源代码到即时本机等的所有组合。一种语言是编译还是解释的语义变得毫无意义。

例如:许多解释语言使用即时字节码编译。C#编译成CIL,JIT编译成native;相比之下,Perl 立即将脚本编译为字节码,然后通过解释器运行此字节码。您只能以 CIL 字节码格式运行 C# 程序集;您只能以原始源代码格式运行 Perl 脚本。

即时编译器还运行许多外部和内部工具。运行时跟踪各种函数的执行,然后调整代码布局以优化其特定执行流程的分支和代码组织。这意味着 JIT 代码可以比本机编译代码运行得更快(就像 C++ 通常是,或者像 C# 通过 IL2CPP 运行),因为 JIT 在运行时会根据代码的实际执行情况调整其优化策略。

欢迎来到计算机编程的世界。我们决定让它变得非常复杂,然后给所有东西附加非描述性的名字。目的是在没有实际意义的单词的定义上引发激烈的争论。

于 2016-01-17T03:05:30.227 回答
15

如果您觉得、了解或老派,编译的 EXE 正在从源代码转换为机器代码,那么 C# 将被解释。如果您认为已编译意味着将源代码转换为其他代码(例如字节码),那么是的,它已转换。对我来说,任何需要运行时处理才能在为其构​​建的操作系统中工作的东西都会被解释。

于 2014-06-27T21:06:01.650 回答
12

看这里:http: //msdn.microsoft.com/library/z1zx9t92

用 C# 编写的源代码被编译成符合 CLI 规范的中间语言 (IL)。

(...)

执行 C# 程序时,程序集被加载到 CLR 中,CLR 可能会根据清单中的信息执行各种操作。然后,如果满足安全要求,CLR 将执行即时 (JIT) 编译,将 IL 代码转换为本地机器指令。

于 2012-01-12T15:18:09.187 回答
7

首先让我们了解解释和编译的定义。

“编译”(当指代代码时)意味着将代码从一种语言翻译成另一种语言。通常从人类可读的源代码到目标处理器可以...处理的机器代码。

“解释”(当提到代码时)也意味着将代码从一种语言翻译成另一种语言。但这一次,它通常用于从人类可读的源代码转换为中间代码,由虚拟机获取,虚拟机将其解释为机器代码。

只是要清楚
源代码 -> 编译器 -> 机器代码
源代码 -> 编译器 -> 字节码 -> 解释器 -> 机器代码

理论上,任何语言都可以被解释编译。通常,Java 被编译成字节码,Java 虚拟机将其解释为机器码。C# 通常被解释为由 CLR、公共语言运行时、另一个虚拟机编译的字节码。

到目前为止,整个事情都是营销噱头。添加了术语“解释”(或至少增加了使用量)以帮助展示即时编译的简洁性。但他们本可以只使用“编译”。区别更多的是对英语语言和商业趋势的研究,而不是技术性质的任何东西。

于 2012-11-20T20:21:39.890 回答
4

C# 在其生命周期中同时被解释和编译。C# 被编译为由 VM 解释的虚拟语言。

混淆源于“编译语言”的模糊概念。

从某种意义上说,“编译语言”是用词不当,因为编译或解释不是语言的属性,而是运行时的属性。

例如,您可以编写一个 C 解释器,但人们通常称其为“编译语言”,因为 C 实现编译为机器代码,并且该语言的设计考虑了编译。

于 2013-01-20T03:41:57.493 回答
3

大多数语言(如果不是全部)都需要一个解释器,将它们的脚本翻译成机器代码,以便让 cpu 理解并执行它!

每种语言处理翻译过程的方式都不同!

例如,“AutoIt”就是我们可以描述为 100% 解释性的语言!

为什么?

因为“AutoIt”解释器在其脚本执行时不断需要!请参见下面的示例:

Loop, 1000
Any-Code

“AutoIt”解释器必须将“Any-Code”翻译成机器代码 1000 次,这会自动使“AutoIt”成为一种慢速语言!

另一方面,C# 处理翻译过程的方式不同,C# 的解释器只需要一次,在脚本执行之前,之后在脚本执行期间不再需要!

C# 的解释器只需将“Any-Code”一次翻译成机器代码,这会自动使“C#”成为一种快速语言!

所以基本上,

  • 在脚本执行期间需要其解释器的语言是“解释语言”!

  • 只需要一次解释器(在脚本执行之前)的语言是“编译语言”!

最后,

  • “AutoIt”是一种“解释语言”!

  • “C#”是一种“编译语言”!

于 2019-01-24T00:53:07.940 回答
1

我相信这是一个相当古老的话题。

从我的角度来看,解释代码将通过解释器,逐行翻译并同时执行。与示例 javascript 一样,它是一个解释代码,当一行 javascript 遇到错误时,脚本就会中断。

在编译代码时,它会通过编译器,一次将所有代码转换为另一种形式的代码,而不是先执行它。执行是在另一个上下文中。

于 2017-10-13T03:42:46.003 回答
0

C# 是可编译语言。

可能,因为我也遇到过这种观点,有人认为有 C# 语言的解释器这一事实,是由于像这样的项目

C# 解释器控制台

或者,例如,著名的

LinqPAD

您可以只编写几行代码并执行它们,这让人认为它是类似于Python的语言,这是不正确的。它编译这些行并执行它们,就像普通的可编译编程语言(从工作流的角度来看)。

于 2012-01-12T15:25:00.470 回答
0

C# 与 Java 一样,具有混合语言处理器。混合处理器执行解释和编译的工作。

于 2015-03-14T18:18:49.070 回答
0

由于计算机只能执行二进制代码,因此任何语言都会导致在某一时刻产生二进制代码。问题是:该语言是否允许您以二进制代码生成程序?如果是,那么它是一种编译语言:根据定义,“编译语言”中的“编译”是指编译成二进制代码,而不是转换成一些中间代码。如果该语言导致为程序生成此类中间代码,则需要额外的软件来从该代码执行二进制编译:它是一种解释性语言。由C#“编译”的程序是否可以在一台机器上直接执行,而这台机器上根本没有安装任何其他软件?如果不是,那么它是一种解释语言。对于解释型语言,它是一个解释器,将生成底层二进制代码,大部分时间以动态方式生成,因为这种机制是此类语言灵活性的基础。雷姆。:有时它看起来并不明显,因为解释器被捆绑到操作系统中

于 2017-08-29T11:20:21.277 回答
0

如果我们同意解释器的定义 «在计算机科学中,解释器是直接执行(即执行)用编程或脚本语言编写的指令的计算机程序,而无需事先将它们编译成机器语言程序。» 毫无疑问:C# 不是解释型语言。

维基百科口译员

于 2017-11-07T08:59:48.067 回答