.net 编译原理

这听起来像是个很是高大上的名字,上学的时候咱们学过的编译原理或者编译技术其实是在讲如何将高级程序语言如C++编译为计算机能够理解的汇编语言,这里说的编译原理只是想说明在.NET的世界里编译这件事儿和传统的C++有什么区别和联系。先来简单的说一下传统的作法,在C++里,但你编译一个应用程序好比一个EXE文件或者是DLL(注意这里的DLL叫作动态连接库,只是到了.NET中才才被叫作程序集)时,实际上编译器作的事情就是直接将你写的C++代码编译为汇编语言,而后以二进制的形式存放在EXE或者DLL文件中,当被执行的时候,CPU就能够直接读到汇编代码开始运行了。固然提及来简单,里面仍是有很是多的细节问题,咱们须要关注的重点是,C++编译器作到的事情是将高级语言直接编译为汇编语言html

 

接下来,咱们来看一看在.NET中咱们如何处理。在说明以前,咱们来回顾一下一个很是经典的说法,你看任何一本介绍.NET的书都会在开篇宣称.NET是跨平台跨语言的高级运行时,可是.NET是如何作到的呢?咱们引入一个很是关键的概念叫作Intermediate Language简称IL,中文叫作中间语言。linux

 

当你写了一段程序(假设是一个Console Application EXE的项目),在Visual Studio中点击F5编译并运行这个按钮的时候,实际上都发生了些什么呢?程序员

  1. 首先是编译,与C++相似,.NET编译器也是将高级语言编译,可是输出并非汇编语言,而是IL中间语言。这个所谓的IL是个什么东西呢?你能够理解为,这是和C#相似的一种语言,程序员能够很容易的看懂甚至直接用Visual Studio就能够写。而后这些中间语言会以二进制的形式存放在EXE文件中。
  2. 接下来是运行。运行的时候.NET Runtime会加载EXE中的必要信息以及IL,这时你可能会问,C++运行的时候,CPU能够直接运行汇编,可是CPU能认识IL么?答案是否认的,CPU会IL一无所知。.NET运行时会进行二次编译,将IL编译为真正的汇编语言,而后CPU执行。

注意,.NET的程序要运行,其实是须要两次编译的,一次是在开发的时候,另一次则是在运行的时候。那么这样作实际上解决了.NET跨语言跨平台这个问题。.面试

 

NET上会不少种语言,好比C#,VB.NET, C++.NET, F#,这些语言开发出来的程序,只要机器上装了.NET Framework就均可以运行,这是由于不一样的语言在第一次(开发过程)编译的时候都会被编译为IL,也就是说,一样的一个功能,用C#写出来和F#写出来编译出来的IL是同样的(固然编译器可能根据不一样的高级语言特色有所优化,可是基本一致)。这样作的好处是什么呢?很简单,好比你用C#写了一个feature,我用F#加载你的DLL就可使用你的程序集了。这看起来没什么,可是你能想一想一下若是C++能够很是简单的调用Java的类库,这个世界是否是就该疯狂了?再来是跨平台,当你的.NET程序运行的时候,.NET运行时负责将IL编译为汇编语言,在运行编译时,.NET能够根据当前运行的操做系统以及CPU构架的不一样生成彻底不同的汇编语言。可是C++就作不到,你用一种编译器编译出来的东西只能运行在某个特定的平台上,好比VC编译器编译出来的只能跑在windows上,在linux上就完蛋了。这是.NET很是重要的一个框架技术核心,虽然如今被应用的并不普遍,由于除了C#和Windows平台意外,.NET是不多被使用的。可是若是将来微软将.NET技术推广到更多领域,这种跨平台跨语言的框架核心就能显示出价值了。看一下下面这个图。windows

 

[.NET <wbr>Framework] <wbr>编译原理

接下来咱们来看几个很是重要的相关的面试问题缓存

 

首先,二次编译带来的性能损失。这很容易理解,与C++相比,运行.NET程序在运行的时候多了一次编译,这确定是要慢的。.NET runtime作了一些性能的优化,即由IL编译过的汇编语言会被缓存起来,当第二次再遇到一样的IL的时候,会直接从内存中加载,而再也不被编译。这也就是.NET程序会被指责第一次运行极慢无比的一个重要缘由。好比咱们来看看下面这段code...框架

 

Console.WriteLine("Hello world"); // first time, compile this function性能

Console.WriteLine("Hello world again"); // second time, load from cache优化

 

固然为了提升性能,.NET编译器容许将高级语言如C#直接编译为汇编语言,可是并不推荐这样作,这样的会,全部跨平台,跨语言的特性就将消失,这种作法适用于对性能要求极高的应用程序。this

 

第二,反编译的故事。全部.NET的DLL都是中间语言组成的,因此,你能够用反编译器加载DLL,由中间语言反编译为C#以此看到其余程序集的源代码。固然.NET提供了加密保护机制,当你编译为DLL的时候能够加入扰码,使反编译器没法理解IL。

 

第三,这是反射的基础。你确定知道反射的故事,在运行时能够动态的加载某个类型中全部的property, field等等,.NET就是经过分析中间语言作到这一点的。在运行时,.NET runtime会加载IL并理解全部的类型定义。

 

 好了,这就是全部.NET编译的基本故事了,虽说和你写code没什么太大关系吧,做为.NET的核心技术框架,这个仍是要了解一下的。That's much for today. [.NET <wbr>Framework] <wbr>编译原理

相关文章
相关标签/搜索