.NET为什么需要CIL和CLR?


11

我在这里看到了这张漂亮的照片。我了解到所有支持.net语言的编译器都将源代码转换为CIL格式。现在,Microsoft永远不会.NET通过为所有操作系统编写CLR来引入所有操作系统。那么为什么要保留这样的中间代码格式和CLR来执行该CIL。这不是要处理的头痛。微软为什么选择这样?

编辑这种架构有其代价。它会降低性能,不是吗?Java这样做是为了保持平台独立性,因为.NET是出于什么原因呢?为什么不保留一个简单的普通C类编译器。如果我需要添加任何新语言,则任何方式都将需要编译器将代码转换为CIL,这唯一的区别就是目标语言。Tat的全部。


3
因为将编译器编写到CIL更容易。而且,向本地编译器编写一个CIL比向每种语言编写本机编译器容易。
Oded

9
@ratchetfreak:这可能是MS未能将CLR移植到其他平台的原因,但它并不是首先拥有CLR的原因(实际上确实使移植变得容易,所以您的论点听起来像MS扑朔迷离,抱歉)
Doc Brown

12
同样是'M $'的低票,这是什么,1998年?
艾伦B

3
埃里克·利珀特Eric Lippert)对此进行了讨论(从第3段开始;前2段与罗斯林有关)。简短的回答是,奥德(Oded)的评论和泰拉斯汀(Telastyn)的回答是正确的。您只需要编码<操作系统数量> + <语言数量>编译器,而不是<操作系统数量> * <语言数量>编译器。
布莱恩

3
@busy_wait:引用的页面提到了一些缺点。例如,“两个应用程序中的配置信息可能导致同一依赖程序集的绑定决定不同”。快速生成可以避免这些问题。这意味着在分发应用程序之后确实需要完成编译(实际上,NGEN必须在每台目标计算机上运行;它不能由分发程序运行)。
布莱恩

Answers:


29

因为他们只需要为CIL编写一个C#编译器-这是困难的部分。与将编译器从C#编写为(每个平台)可执行代码相比,为每个平台制作CIL解释器(或更常见的是,即时编译器)相对容易。

除此之外,运行时还可以处理编译为CIL的所有内容。如果您想要一种新语言(例如F#),则只需为其编写一个编译器,即可自动神奇地获得.NET支持的所有平台支持。

哦,我可以将一个.NET dll并通过Mono在Windows或Linux上运行,而无需重新编译(假设我的所有依赖关系都得到满足)。

至于性能,这值得商bat。本质上,有些“预编译器”采用CIL并生成本机二进制文件。其他人则认为即时编译器可以进行优化,而静态编译器根本无法做到。以我的经验,这在很大程度上取决于您的应用程序在做什么以及在哪个平台上运行(主要是JITer在该平台上的性能如何)。对我来说,遇到.NET不够好的情况是非常罕见的。


“翻译”?我以为MS总是只提供JITter?
布朗

1
@DocBrown-嗯,是的-我误称了。定影。
Telastyn 2013年

+1,您能为我的编辑加点说明吗,以便我接受此答案
vikkyhacks 2013年

高性能运行时通常将解释器和JIT编译器结合在一起(混合模式执行)。我不确定.NET,但是许多Java VM使用这种方法。
Cyanfish

2
@busy_wait:各种各样的事情。方法内联,复制传播,删除不必要的代码,将乘法/除法转换为移位,其他使用readonly字段的算术运算。传统编译器可以执行其中的一些优化,但前提是可以通过静态分析检测到它们。相比之下,一个抖动可以在运行时发现(例如)一段代码没有做任何有用的工作,因为它修改的对象或变量没有在其他地方引用。我不是抖动专家,但这基本上是动态分析与静态分析的威力问题。
Aaronaught

14

.NET具有中间语言(CIL / MSIL)以及与平台无关的运行时(CLR)的特定于平台的实现,其原因与Java相同。Microsoft打算让C#直接与Java竞争,并且可以在Microsoft定位的OS(它自己的OS)上与Java竞争。

即使仅在Windows平台(或具有Mono或Linux之类的.NET的其他操作系统)上支持.NET,其优点也类似于Java:

  • 托管内存运行时-与非托管C / C ++不同,C#/ VB.NET开发人员不必担心严格控制对象生存期。像Java一样,CLR具有垃圾收集器,该垃圾收集器会自动释放堆中离开范围的对象。尽管对于那些习惯于非托管运行时的人来说,这似乎微不足道,但它具有阻止C / C ++中如此普遍的指针算法的“黑魔法”的极端次要优势。
  • 平台独立性-Windows Vista和Windows 7与Windows XP的工作方式不同。Windows 8的工作原理仍然不同。Windows Mobile版本(包括Windows 8 Mobile)再次工作不同。不同的硬件,不同的体系结构,不同的功能。尽管目标环境对.NET开发人员仍然很重要,但是与为所有这些OS构建兼容的C / C ++程序所必需的知识相比,专业知识的数量已大大减少。AC#开发人员可以免费获得更多。
  • Web应用程序支持-我还没有看到用C ++从头开始编写的面向客户端,服务器脚本的Web应用程序。Web 服务器,当然,Apache,ISS,它们通常都是出于速度/效率的原因而针对非托管运行时运行。但是,C ++不是用于构建Web应用程序的语言。C#是(Java也是如此)。它是从头开始设计的,以支持下一代Microsoft的ASP范例。这是旨在在沙箱中运行的代码;哪个沙箱(ISS的ASP.NET插件或“桌面” CLR)相对不重要。
  • 语言/运行时独立性-C ++编译器采用C ++源代码,并使用一种机器语言为一种处理器体系结构生成汇编代码。为了支持不同的体系结构和/或机器语言,必须编写一个全新的编译器(并且必须编译一组全新的运行时库)。AC#编译器采用C#源代码并生成CIL,特定于硬件的JITer将其转换为机器代码。不管源语言是什么,同一个JITer都可以翻译任何CIL程序(并且有几种; C#,VB.NET,F#和大量的“ Iron”语言端口,例如IronHaskell,IronRuby,IronLisp等)。相同的编译器可以将一种语言转换为任何JITer都可以运行的CIL,而不管其硬件是什么。
  • 专注于“正确的”代码-对于C ++开发人员,有很多“正确”的方法可以执行某些操作,具体取决于最重要的内容。内存效率,CPU效率,硬件独立性,操作系统独立性等。当这些优先级都很高时,代码看起来可能会大不相同。C#是由一个小组设计的,该小组深深吸取了Fowler和他的同事的概念课程(他们正在通过向面向C的社区大力推广面向对象的原理来在C ++社区中改革代码设计),以及之前的语言(包括Java,及其对全能对象的近乎狂热的服从)所学到的实践经验,当一个好的旧的C ++风格的函数指针可以更干净地完成工作,并且不亚于任何对象时,面向)。

出于反托拉斯的原因,MS小心不要在其他主要平台(例如Android,Mac OSX / iOS和Linux)上过分“干扰”。但是,确实确实有针对这三个平台的团队开发。它是由MS开发的Office for OSX版本,有许多应用程序,包括适用于iOS和Android的Office互操作应用程序,在Linux上运行的Skype(现在是Microsoft产品),甚至有人认为Microsoft对Linux内核有所贡献(主要是在Linux内核中)。虚拟化心态)。


1
“我还没有看到用C ++从头开始编写的面向客户端,服务器脚本的Web应用程序。” -您将CGI放在哪里?我的第一个Web应用程序(虽然微不足道)是100%C。那时(90年代中期),用cgi编写用于执行标准工作的.c和.h比较容易(“脚本”语言只是也出现在现场)。

嗯... CGI,CGI ...我想我听说过,但是我和KeithS在一起,我还没有真正看到一个:)
DXM

@DXM动态内容的旧模型是用于Web服务器的一个进程,将进程放入标准位置(查询参数等放入特定的环境变量中)-通用网关接口。然后,该过程的输出作为内容发送回。在过去,找一个了解C或C ++而不是perl或python的程序员会更容易(而sh对于这样的工作非常笨拙)。

1
不要低估与Java相似的重要性。Sun刚刚针对MS的JVM端口起诉了MS,并赢得了一些法律要点(愚蠢的IMHO)。CIL和CLR受此启发,您会注意到J#尽可能接近Java,而不会触发进一步的法律诉讼。巨大的区别是CLR与语言无关。如果需要,您确实可以混合使用C#,F#和J#编写程序。只需尝试将Java与其他语言的库混合并获得稳定的程序。
RBerteig

1
但是MSIL和本机代码之间的互操作已被很好地定义并且可以正常工作。显然希望它仅通过设计和用户社区的态度来工作。
RBerteig

12

Windows操作系统可用于不同的CPU类型,今天主要是x64,x86,Intel,ARM。

CIL / CLR独立于该硬件平台-IL执行环境“消除了”这些差异。例如,为“任何CPU”编译的.NET程序集通常可以在Win64上作为64位进程执行,而在Win32上作为32位进程执行,而无需提供其他可执行文件。

此外,CIL允许将元数据存储在程序集中,这对于本机DLL是不容易实现的(当然,MS以前可能使用COM组件做到了这一点,但是该技术从未像.NET组件那样容易处理)。这使得软件组件的创建变得非常简单,并且是所有.NET语言中反射/自省的基础。


只是要补充一点,它们不仅允许使用不同的CPU类型,而且甚至允许使用同一CPU类型(例如所有x64)中的不同版本(Core i3 / i5 / i7)和供应商(Intel与AMD) JIT编译器可以利用的汇编指令集
DXM

2
@DXM:您知道JIT实际上吗?还是这更是假想的?
布朗

至少一个MSDN博客声称JIT编译器确实做到了(或者8年前做到了)。

@DocBrown:显然我手头没有任何参考资料,但我想我很早以前就记得读过一些东西。感谢delnan,找到链接。这是有道理的,因为我们知道芯片制造商希望在标准x86-x64之上添加自己的指令,因此如果该机器可以利用,为什么不呢?
DXM
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.