初学.NET肯定会有一系列的疑问,比方(下面为自己的疑问):
1) 何为. NET框架。它都包括哪些东西?
2) 程序集是什么。它是怎样在CLR(通用语言执行时)中执行的?
3) C#与VB.NET同属于.NET平台,它们之间的根本联系和差别,为何他们之间的程序集能互相调用(假设创建一种新型的面向. NET的语言,要遵循什么)?
想要明确如上问题,就须要弄清楚CIL(通用中间语言)、CLR(通用语言执行时)、CTS(通用类型系统)、CLS(通用语言规范)等等的概念,以下是自己看了一些他人的文章后进行的简单总结。
首先通俗地理解一下.NET平台、.NET框架(Framework)的概念
“平台”(这里指软件技术平台,以下都指的是这个)就是可以独立执行并自主存在。为其所支撑的上层系统和应用提供执行所依赖的环境。提取一下就是,平台是一个环境。仅仅要符合平台规范的应用都能扔到上面来执行。
我的通俗理解.NET平台是.NET应用与操作系统之间的一个中介,首先它为.NET应用执行提供了环境。其次它为.NET应用与操作系统之间起到了“解耦”的作用。使得平台上层的应用不依赖与操作系统(的机器指令集)。
至于怎样解耦,要看它的编译过程,以下会进行解释。
框架就好似某种应用的半成品,是前人依据经验开发的可复用的一组组件。供你选用。然后添血加肉完毕你自己的系统。其思想与设计模式有些相似,框架是代码复用,设计模式是设计复用。框架又好似提供的一组规范。它规范应用系统的开发与部署,众所周知的J2EE框架就是定义了13个规范。相类似。NET Framework也提供了非常多规范。以下会进行介绍。
粗略地说。一个.NET应用是一个执行于.NET Framework之上的应用程序。或者。一个.NET应用是一个使用.NET Framework类库来编写。并执行于公共语言执行时CLR(通用语言执行时)之上的应用程序。以下開始解决上面提出的问题:
程序集及其执行
首先引出两个概念CIL——通用中间语言、CLR——通用语言执行时两个概念(详细概念看百度百科)。
我们知道,普通的无平台应用(比如:VB应用程序)经过预编译、编译、汇编、链接几个步骤后,终于生成的可执行文件里就已经包括了本地处理器的代码,支持它执行的是操作系统和本地的机器指令集。
在.NET框架下。高级语言(例C#)经过编译后生成的结果文件被称做程序集,其后缀名是.dll(类库)或.exe(可执行程序,控制台应用程序编译结果)。
而程序集并非二进制机器码,是不能直接执行的。须要经过CLR(通用语言执行时)的即时编译才干生成被操作系统所识别的机器码。
以下我们用C#和VB.NET分别写两个同样控制台应用程序,都定义一个字符串“hello world”,然后输出:
C#:
VB.NET:
然后经过编译,分别生成对应的程序集.exe文件。以下我们用vs自带的反编译工具-IL DASM(文件夹:開始-- >vs2010-- >Windows SDK Tools -- >IL 反汇编程序)分别打开上面生成的程序集。
C#程序集:
VB.NET程序集:
对照两个程序集文件。能够发现两者的代码差点儿全然一致。
上面用IL DASM打开的文件里的类似汇编的代码即为CIL-通用中间语言。能够看到VB.NET与C#,编译后生成的程序集的格式是同样的;当程序所实现的功能同样时,程序集所包括的CIL代码也是类似的。由此可得下图:
上面提到了程序集(CIL)并非CPU能够直接运行的本地机器语言。这样的语言还须要.NET运行时(CLR)环境的支持。在运行之前。进行一个被称为即时编译的二次编译过程。才干转变成计算机能够识别的指令。
CIL也是一种程序语言,它是比C#低级。比机器码高级的一种中间码语言。类似Java中的.Class文件。从前面截图可知CIL是一种基于堆栈的语言。同一时候,它提供了class、interface、继承、多态等诸多面向对象的语言特性,因此它又是全然面向对象的语言。假设愿意。甚至能够直接编写CIL代码。而且使用CIL的编译工具IL ASM(IL Assembler,IL汇编程序)来对它进行编译。仅仅只是,和大多数低级语言一样,这样的方式会使开发效率会变得非常低。
C#源程序在被编译为程序集以后。就独立于C#,因此程序集能够由其它种类的语言所调用;同一时候,由于程序集并没有包括本地机器的指令,所以它与详细的机器类型也分隔开了,能够被装有.NET框架的不论什么机器执行。
C#与VB.NET的根本联系与差别
(下文大部分引用一些书籍或博文)
这里要引入CTS——公共类型系统、CLS——公共语言规范两个概念。
设想我们怎样开发一套类似C#或VB.NET的新的语言(编译后生成CIL代码,能够在.NET环境下执行)?
要开发的新语言相当于CIL的高级语言版本号。所以实际上要做什么并非由新语言决定的。而是由CIL来决定的。因此,须要一套CIL的定义、规则或标准。这套规则定义了我们的语言能够做什么。不能够做什么。具有哪些特性。
这套规则就称作CTS(Common Type System。公共类型系统)。不论什么满足了这套规则的高级语言就能够称为面向.NET框架的语言。C#和VB.NET只是是微软自己开发的一套符合了CTS的语言,实际上还有非常多的组织或团体,也开发出了这种语言,比方Delphi.Net、FORTRAN等。
CTS规定了能够在语言中定义的数据类型、訪问级别比方Private、Public、Family(C#中为Protected)、Assembly(C#中为internal)、Family and assembly(C#中没有提供实现)、Family or assembly(C#中为protected internal)。
CTS还定义了一些约束,比如。全部类型都隐式地继承自System.Object类型。全部类型都仅仅能继承自一个基类。从CTS的名称和公共类型系统能够看出,不仅C#语言要满足这些约束,全部面向.NET的语言都须要满足这些约束
上面提到了,C#并没有提供Family and assembly的实现,C#中也没有全局方法(Global Method)。换言之,C#仅仅实现了CTS 的一部分功能。也就是说,CTS规范了语言可以实现的所有能力,可是符合CTS规范的详细语言实现不一定要实现CTS规范所定义的所有功能。
显然,因为CIL是.NET执行时所能理解的语言。因此它实现了CTS的所有功能。
尽管它是一种低级语言,可是实际上,它所具有的功能更加完整。
C#语言和CIL的关系。能够用例如以下表示:
既然已经理解了CTS是一套语言的规则定义,就能够开发一套语言来符合CTS了。如果这个语言叫做B#,它所实现的CTS非常有限,仅实现了当中非常少的一部分功能。它与CTS和C#语言的关系可能例如以下:
那么如今就有一个问题:由C#编写的程序集,可以引用由B#编写的程序集吗?答案显然是不能。尽管C#和B#同属于CTS旗下,可是它们并没有共通之处。因此,尽管单独的B#或C#程序可以完美地在.NET框架下执行,可是它们之间却无法相互引用。
假设B#项目期望其它语言类型的项目可以对它进行引用。就须要B#中公开的类型和功能满足C#语言的特性,即它们须要有共通之处。B#中不公开的部分(private、internal、protected)是不受影响的。可以使用独有的语言特性,由于这些不公开的部分本来就不同意外部进行訪问。因此。假设B#想要被C#所理解和引用,它公开的部分就要满足C#的一些规范,此时,它与CTS和C#语言的关系就会变成例如以下:
假设世界上仅有C#和N#两种语言就好办了。把它们共同的语言特性提取出来。然后要求全部公开的类型都满足这些语言特性,这样C#和N#程序集就能够相互引用了。可问题是:语言类型有上百种之多。而且.NET的设计目标是实现一个开放的平台。不仅现有的语言经过简单改动就能够执行在.NET框架上,兴许开发的新语言也能够,而新语言此时并不存在。怎样提取出它的语言特性?因此又须要一套规范和标准来定义一些常见的、大多数语言都共同拥有的语言特性。
对于未来的新语言。仅仅要它公开的部分可以满足这些规范。就行被其它语言的程序集所使用。这个规范就叫做CLS (Common Language Specification,公共语言规范)。非常明显,CLS是CTS的一个子集。那么VB.NET、C#、B#的关系就可表达为:
假设利用C#开发的一个程序集的公开部分仅採用了CLS中的特性。那么这个程序集就叫做CLS兼容程序集(CLScompliant assembly)。显然,对于上面提到的FCL框架类库,当中的类型都符合CLS,仅有极个别类型的成员不符合CLS,这就保证了全部面向.NET的语言都能够使用框架类库中的类型。
满足CLS就是要求语言特性要一致。那么什么叫做语言特性?这里给出几个详细的语言特性:是否区分大写和小写,标识符的命名规则怎样,能够使用的基本类型有哪些,构造函数的调用方式(是否会调用基类构造函数),支持的訪问修饰符等。
那么我们怎样检验程序集是否符合CLS呢?.NET为我们提供了一个特性CLSCompliant,便于在编译时检查程序集是否符合CLS。我们来看以下一个样例:
能够注意到,在CLSTest类的前面为程序集加上了一个CLSCompliant特性,表明这个程序集是CLS兼容的。可是。有三处并不满足这个要求,因此编译器给出了警告信息。
这三处是:
?不能以大写和小写来区分成员,因此字段name和方法Name()不符合CLS。
?方法的返回类型和參数类型必须是CLS兼容的,uint和sbyte类型并不是CLS兼容,因此GetValue()和SetValue()方法不符合CLS。
?标识符的命名不能下面划线“_”开头,因此属性_MyProperty不符合CLS。
还会注意到,编译器给出的仅仅是警告信息,而非错误信息,因此能够无视编译器的警告,只是这个程序集仅仅能由其它C#语言编写的程序集所使用。
总结
我们对.NET框架的第一感觉就是,.NET框架所提供的庞大类库及编写代码所採用的C#语言等。实际上远不止这些。
还包括很多的内容,比如CLI、CIL、CTS、CLS、CLR、JIT、BCL、FCL等,这些内容在《.NET之美》这本书中都进行了深入浅出的解说,对刚開始学习的人非常有用。假设想真正的理解.NET,只会编码是远远不够得,上面这些东西才是根本。