一、.NET源代码编译过程

由于Microsoft 在 .NET 平台上提供 3 种语言 – C#、F# 和 Visual Basic,所以, .NET被设计成本质上并不知道所运行的程序代码到底是哪种语言,因为.NET只认识IL语言。IL语言即 Intermediate Language (微软中间语言)。为了说清楚整个事件的来龙去脉,我们以C#源代码为例。

首先,程序员利用Visual Studio开发C#的源代码,然后语言编译器(Language Compiler)将源代码编译为IL中间语言,实际上是一些元数据和中间语言指令,接着在运行这个IL程序时,JIT编译器将根据系统环境将IL中间语言指令转换为机器码。

这里面有一个疑问,为什么不一开始就直接编译成机器码,而是编译成IL中间码?

.NET的基元类型(Primitive Type)_命名空间

JIT的全名叫即时编译器,它是在运行时环境中发生的编译行为。不同的CPU或操作系统的环境是不同的,为了实际跨平台运行C#程序,所以只能一开始将源代码编译成IL中间码,等到实际运行时,再根据当前的CPU或操作系统环境将IL中间码由JIT编译成机器代码。

所以,对于.NET的CLR运行时而言,它只认识IL中间码,不在乎这个中间码是C#编译而来,还是由VB编译而来。正是因为 C#、F# 和 Visual Basic都可以开发.NET应用程序,.NET 为了能与多种编程语言代码进行交互,于是它制定了一个通用类型系统 (common type system,CTS),要求所有语言都必须遵守这个约束。

二、通用类型系统 (CTS)

请注意,CTS是一个非常重要的知识点,程序员一定要理解它存在的必要,以及它的职责范围。因为程序员在本质上是申请内存,操作内存数据,归还内存的过程。要申请多大的内存,这个就要看CTS的脸色。CTS将内存分成多种类型,为了节约内存资源,有短一点的只占一个字节长度的内存,也有稍长一点的占4个字节的内存,或者8个字节的内存等等。还是那句话,按需申请。

CTS要面临可能来自C#、F#或VB语言的内存申请要求,所以为了方便统一管理,于是提供了一系列标准的基元类型(Primitive Type),不管是C#程序员,还是VB程序员,在申请内存时,都得按这个基元类型表进行申请。我的地盘我说了算!

除此之外,CTS还拥有其它的功能:

  • 建立用于跨语言执行的框架。
  • 提供面向对象的模型,支持在 .NET 实现上实现各种语言。
  • 定义处理类型时所有语言都必须遵守的一组规则。
  • 提供包含应用程序开发中使用的基本基元数据类型(如 BooleanByteChar 等)的库。

在本节课程中,我们先了解一下CTS提供了哪些基本基元类型(Primitive Type)。因为除了BooleanByteChar属于基元类型,像类、结构、枚举这些也是基元类型,但它们不算基本基元类型。

重庆教主友情提示

其实,我们学习C#语言这门课程时,大多数时候都是在学习CTS的基元类型

三、基本基元类型(Primitive Type)

编译器直接支持的数据类型称为基元类型(primitive type)。基本的基元类型如下表所示:

基元类型名称

说明

范围

System.SByte

有符号8位值

System.Byte

无符号8位值

System.Int16

有符号16位值

System.UInt16

无符号16位值

System.Int32

有符号32位值

System.UInt32

无符号32位值

System.Int64

有符号64位值

System.UInt64

无符号64位值

System.Char

16位Unicode字符

System.Single

IEEE32位浮点值

System.Double

IEEE64位浮点值

System.Boolean

true/false值

System.Decimal

128位高精度浮点值,常用于不容许舍入误差的金融计算

System.String

字符数组

System.Object

所有类型的基类型

这些基元类型都定义在System命名空间当中,如果要使用其中的基元类型,则必须指明它的命名空间或者通过using将System命名空间引入到源文件的开头。

虽然.NET提供了这些基元类型,但是,C#、F#、VB也拥有属于自己的基础数据类型,以及声明这些基础数据类型的关键字。比如,在C#中我们用string定义一个字符串,在.NET中用String定义一个字符串,所以C#的基础数据类型基本上与.NET的基础基元类型有着一一对应的关系。

我们在下一节来介绍两者的对比关系。

——重庆教主 2023年12月19日