.net 的一些基本概念搞得头晕,索性整理一下
首先自然就是CLR:common language runtime,在C#中,是由这个东西掌握着程序的运行,它可以被不同的语言所采用,事实上,CLR并不管你在运行什么代码,因为它只和一个东西打交道,叫做managed module,managed module是一个CLR才能运行的portable excutable文件,所有面向CLR的源代码最后都会被编译成为managed module。managed module是一个PE文件,它里面包含了很多内容,①PE表头:用来指明文件类型;②CLR表头:主要内容是需要CLR怎么搞定它;③mentadata表:用来记录源代码中定义的类型和成员,以及源代码引用的类型和成员;④IL代码:这当然就是CLR所理解的平台无关的语言了。CLR有强大的功能,一般而言,没有一种高级语言能够完全体现它的所有功能(IL除外),高级语言,如C#只能实现它的一个子集。所以,在.net中,各种语言的合作不仅是可能的,而且有时候是必需而有效的。
当然了,managed module只是一个概念,真正同CLR发生作用的是assembly,它是一个或者多个managed module,如果一个assembly里面只有一个managed module并且没有其他资源,那么这个assembly就是一个managed moudle,但如果有几个的话,那么一个assembly文件事实上意味着多个文件的联合。这种联合通过一张manifest来表明(manifest说白了其实就是一张mentadata表的集合,通过它们描述了组成程序集的文件,公用导出类型,数据,文件等)。.net事实上允许一个assembly里面有多个manged module,而且可能是不同语言的,而且,还可以被部署在不同地方(在这种情况下,就得用到一种叫做Assembly Linker的工具,al.exe来完成)。一个关于assembly的特性,它是self-describing的,它不需要额外的信息,所以才能如此方便的部署。
至于第一段提到的IL,显然就是intermediate language,它有点像一种机器语言,但同时它是CPU无关的,并且支持面向对象机制。所以,可以认为它是一种面向对象的CPU无关语言。
IL能够直接看懂,用ildasm.exe就可以直接看IL的内容。
前文已述说,IL是同CLR紧密结合的,它能够完成CLR所有的功能。就目前而言,CPU还不能直接运行IL指令,所以运行IL代码,必须先把它编译成为机器指令,CLR中的JIT:just-in-time完成这个功能。
JIT是一个实时编译器,在运行IL的时候进行编译。具体编译方法从略,但是有几点:
1. 在第一次遇见某个函数的时候,JIT会将它编译成本地CPU指令,然后每次遇见相同函数就直接去执行已经放到内存中的本地CPU指令,所以,性能损失实在第一次调用某个函数的时候;
2. 程序在运行完以后,在动态内存中的本地代码被丢弃,所以,重新运行必须重新编译;
3. JIT的效果颇不见得比直接编译成本地指令差,事实上,因为寻常编译器通常是面向最小CPU指令集的,所以,它很难使用到一些扩展功能,而JIT在某种程度上同CPU分开,所以可以完成一些较为智能的优化;
4. 也可以利用NGen.exe这个工具永久保存机器代码,但它对性能的估计将比较保守。
CLR中所有的内容都是围绕着类型的,MS为了给这些类型制定了一个正式的规范,叫做CTS:common type system,这个系统的功能在于用一种统一的方式描述类型的定义和行为(注意,它统一的是描述方法,而不是类型,类型可以创造,无法统一,统一的是描述的方法,所以,如果用不同的高级语言描述同一种类型,在最后编译为IL的时候,因为有CTS的存在,所以不同高级语言最后得出的类型描述方法是一样的,类型的行为是一样的,与语言无关的)。
CLS:common language specification,公共语言规范,是为了进行多种语言的结合使用而提炼出来的所有语言都必须支持的特性集合,面向CLR的所有语言都必须支持CLS,所有同CLS兼容的语言都可以使用CLS中定义的特性。
所以,如果希望自己的类型能够被其他语言所使用,那么,应该保证她在CLS内,或者说,他所给出的“公有导出类型”(也就是准备给人家用的类型)必须是在CLS内的。比如,CLS中必须做到non-case-intensive,大小写无关,因为虽然c++和c#大小写相关,但是vb大小写无关,则必须满足这种互操作性。
暂时就是这些,最简单,但是新东西总是让人头晕。