本学习主要参考Andrew Troelsen的C#与.NET4高级程序设计,这小节主要述说以下几个东西:
宏观上讨论一下.net相关的主题:程序集、CIL(Common Intermediate Language,公共中间语言)和JIT(just-in-time,即时)编译。还有阐述一下.NET Framework不同方面之间的关系:CLR(公共语言运行库)、CTS(公共类型系统)、CTS(公共语言规范)。
最后将会简单阐述一下.NET的基础类库(缩写为BCL或者FCL)和语言平台无关性。
.NET framework的一些核心功能:
1、对已有代码具有完全的互操作性:已有的com二进制组件可以喝更新的.net二进制组件共存,反之亦然。在.net4中,使用dynamic关键字可以大大简化这种互操作性。
2、支持多重编程语言:使用多种编程语言(C#、Visual Basic、F#和S#等)创建.net应用。
3、所有支持.net的语言共享的公共运行时引擎:这个引擎的一个特点是具有一组明确定义的类型,而每一种支持.net的语言都能‘明白’这些类型。
4、全面和彻底的语言集成:.net支持跨语言的继承、异常处理和代码调试。
5、全面的基础类库:这个库隐藏了原始api调用的复杂性外,还提供了被所有支持.net的语言所使用的一致的对项模型。
6、不关注com底层操作:IClassFactory、IUnknown、IDispatch、IDL代码和讨厌的于变量兼容的数据类型(如BSTR、SAFEARRAY等)不会出现在.net二进制代码中。
7、真正简化的部署模型:在.net环境下,不需要将二进制单元注册到系统注册表了。另外,.net允许同一个*.dll的不同版本存在于同一台机器上。
.net的平台构造块(CLR、CTS、CLS)简介:
运行库层的正式名称是CLR:从程序员的角度看,.net可以理解为一个运行库环境和一个全面的基础类库。其主要的作用是为我们定位、加载和管理.net类型,同时也负责一些低层细节的工作,如内存管理、应用托管、处理线程、安全检查等。
构造块CTS(公共类型系统):CTS规范完整描述了运行库所支持的所有可能的数据类型和编程结构,指定了这些实体间如何交互,也规定了他们在.net元数据格式中的表示。
CLS(公共语言规范):一种特定的支持.net的语言可能不支持CTS所定义的所有特性。CLS定义了一个让所有,net语言都支持的公共类型和编程结构子集。这样,如果够早的.net类型仅公开了与cls兼容的数据类型或编程结构,就不能保证所有的.net语言能和你的.net代码库相交互。
基础类库:
除了CLR和CTS/CLS规范之外,.net平台提供了一个适用于全部.net程序语言的基础类库(BCL)。这个基础类库不仅封装了各种基本类型,如线程、文件输入/输出(I/O)、图形绘制以及与各种外部硬件设备的交互,还支持在实际应用中用到的一些服务。基础类库定义了一些类型,方便了数据访问、xml文档的操作、安全和基于web(以及传统的桌面和基于控制台)的前端的构造。如下图,可以从宏观上看到clr、cts、cls和基础类库(BCL)之间的关系。
.net程序集概览:
不管选择了哪种.net语言编程,需要明白的是,尽管.net二进制文件与com服务器和非托管Windows二进制文件(*.dll或*.exe)具有相同的文件扩展名,但它们的内部却是完全不同的。例如,*.dll的.net二进制文件不会导出与com运行库进行通信的方法(因为.net不是com)。
此外,.net二进制文件不适用com类型库文件描述,而且不用再系统注册表种注册。也许更重要的是,.net二进制文件不包含特定的平台的指令,它包含的是平台无关性的IL(中间语言)和类型元数据。下图显示了这个流程:
说明:在.net的开发过程中,IL的官方术语是MSIL(微软中间语言)。然而,在最终发布的.net中,该属于改为了CIL(公共中间语言)。因此在阅读.net资料时,我们应该明白IL、MSIL和CIL指的是同一个概念。
CIL:概念上类似于java的字节码,因为它只在绝对必须的情况下才编译为特定的平台的指令。绝对必须通常指一段CIL指令被.net运行库引用时。
元数据:元数据详尽描述了二进制文件中每个‘类型’的特征。.net元数据总是存在并且会由某种支持.net的编译器自动生成。
清单:描述程序集本身的元数据,清单记录了程序集单签的版本信息、文化信息和正确执行所需的外部引用的程序集的列表。
程序集、命名空间和类型的区别:
我们都知道代码库的重要性,像MFC、javaEE和ATL这些代码库给程序员提供了一套定义明确的既有代码,可以显著地提高开发效率。C#没有提供特定语言的代码库,但是C#程序员可以利用一种语言无关的.net代码库。为确保基础类库中所有的类型能良好地组织在一起,.net平台提出了命名空间的概念。
命名空间:简单地说,命名空间就是一个程序集内相关类型的一个分组。(方便我们从逻辑上理解和组织关联类型的方式。)例如,System.IO命名空间包含了有关文件i/o的类型。需要特别指出的是,一个程序集可以包含任意个命名空间,每个命名空间又可以包含多种类型。
程序集:除了通过c#的using关键字来指定命名空间,还需要告诉C#编译器包含引用类型的实际CIL定义程序集的名字。大多数.net framework程序集都位于成为全局程序集缓存(GAC)的指定目录下。默认windows在C:\Windows\Assembly下。
using关键字只是特定类型的完全限定名的简单速记符号,每种方法最后都会得出相同的底层CIL(事实上,CIL代码总是使用完全限定名),并且对程序集大小和性能没有任何影响。
.NET的平台无关性:
要理解它是如何做到的,需要掌握.net领域中的另一个缩写词CLI(公共语言基础设施)。
当微软发布C#语言和.net平台时,也发布了一整套正式的文档来说明C#和CIL语言的语法和语义、.net程序集格式、核心.net命名空间以及假定的.net运行时引擎的结构(叫做虚拟执行系统,即VES)。
让我们高兴的是,这些文档已经提交到ECMA,并被ECMA批准成为官方的国际标准,这些规范包括:
ECMA-334,C#语言规范;
ECMA-334,公共语言基础设施(CLI)。
她们可以使第三方组织在各种操作系统和处理器上构造不同的.net平台发行版,理解了这一点,这些文档的重要性就显而易见了。
小结:
.net本质上就是一个运行库执行引擎(mscoree.dll)和基础类库(mscorlib.dll等)。CLR可以承载任意符合托管代码规则的.net二进制文件(又称程序集)。而程序集中有很多的CIL指令(以及类型元数据和程序集清单),这些指令通过即时编译器(JIT)编译成为特定平台的指令。