包含内容:
- C#处理内存分配和回收策略
- C#执行类型检查方法
- C#与其他编程语言的互操作,跨平台处理
CLI,Common Language Infrastructure, C#编译和执行所依赖的一个公共语言基础结构。
C#生成一种中间语言指令,即CIL。在执行时,CIL才被转换为机器码。同时,还需要运行时负责加载和运行程序,提供类似安全保障,垃圾回收等额外服务。以上内容都被写入了CLI中,成为国际性规范,所以说CLI是C#的执行环境和与其他语言交互的一个规范。
跟C与C++不一样的是,C和C++是直接编译成机器码,所以这些语言的平台是底层操作平台和机器指令集,即Linux,Windows等。而C#的底层平台是运行时,运行时可以理解CIL语言,使用内部的即时编译器(Just-In-Timecompiler)完成CIL到机器码的编译过程。当程序安装或者执行的时候便可能发生JIT编译,大多数发生在执行时。
.NET包含NGEN工具,能在运行程序之前将代码编译成机器码,会评估机器的特性,生成高效的代码,如Unity项目中的LuaJit文件夹。在安装程序时使用NGEN,可以缩短程序的JIT编译导致的启动时间。另外,CLI也允许解释执行,这个特性使得C#能够很好地与脚本语言一起执行。
VS2015后的版本支持本机.NET,可以在创建部署版本的时候,将C#代码编译成本机机器码。在运行时下执行的代码称为托管代码,数据所需的内存是运行时自动分配回收的。由于代理的存在,可以存在一些额外的服务,比如异常处理,安全信息访问等。
在运行时中内置了垃圾回收此服务,具体的工作方式并不固定。被垃圾回收的对象不一定会进行确定性回收,即在定义好的,编译时已知的位置进行回收。垃圾回收器只负责内存管理,而不会释放除了内存以外的资源。
大多数CLI使用的是generational, compacting, mark-and-sweep的回收算法。下面简单解释:
- generational : 经历过垃圾回收且存活下来的对象,会比只存活过 短时间的对象,更晚地被清理掉。
- compacting : 将被回收的对象会被压缩到一起,确保没有脏空间。
- mark-and-sweep : 每次执行辣鸡回收的时候,都会标记出将要回收的对象。
使用压缩机制使得新对象能快的实例化,而不需要搜索内存找分配空间,同时降低了分页的概率,因为同一页能存储更多对象。另外,垃圾回收会考虑到机器资源,当计算机内存余量较大时很少清理资源。
运行时的另一个优点是它的类型检查能力,能够防止非法类型转换导致的缓冲区溢出安全漏洞。在运行时,会进行以下的类型检查:
- 变量和变量引用的数据都有类型,变量的类型兼容引用的数据类型。
- 局部分析一个类型,确定需要什么权限来执行该类型的成员
- 每个类型都有一组编译时定义的方法和数据,,强制规定了可以访问方法和数据的类型。
当有相应权限时,可以通过反射机制绕过分装和访问修饰符,反射机制允许浏览类型成员,晚期绑定,在对象中查找特定构造,调用类型成员等功能。运行时根据权限允许或者禁止特定类型的操作,根据程序创建者控制执行。CAS,Code Access Security ,还能识别代码的位置,比如本地的代码比起互联网的代码受信任,提供者的身份标志被嵌入程序证书。
平台可移植性,指的是不需重新编译,代码的移植工作由运行时来实现。必须不能使用某个平台的API,但是这又带来了更多的不便利。在VS中有支持通用应用程序。