C# 有两种类型:值类型 和 引用类型。 值类型的变量直接包含它们的数据。 引用类型的变量存储对数据(称为“对
象”)的引用。 对于引用类型,两个变量可以引用同一个对象;对一个变量执行的运算可能会影响另一个变量引用
的对象。 借助值类型,每个变量都有自己的数据副本;因此,对一个变量执行的运算不会影响另一个变量( ref
和 out 参数变量除外)。
标识符为变量名称。 标识符是不包含任何空格的 unicode 字符序列。 如果标识符的前缀为 @ ,则该标识符可以
是 C# 保留字。 在与其他语言交互时,使用保留字作为标识符很有用。
C# 的值类型进一步分为:简单类型、枚举类型、结构类型、可以为 null 的值类型和元组值类型。 C# 引用类型又
细分为类类型、接口类型、数组类型和委托类型。
以下大纲概述了 C# 的类型系统。
C# 程序使用 类型声明 创建新类型。 类型声明指定新类型的名称和成员。 用户可定义以下六种 C# 类型:类类
型、结构类型、接口类型、枚举类型、委托类型和元组值类型。
class 类型定义包含数据成员(字段)和函数成员(方法、属性及其他)的数据结构。 类类型支持单一继承和多
形性,即派生类可以扩展和专门针对基类的机制。
struct 类型定义包含数据成员和函数成员的结构,这一点与类类型相似。 不过,与类不同的是,结构是值类
型,通常不需要进行堆分配。 结构类型不支持用户指定的继承,并且所有结构类型均隐式继承自类型 object
。
interface 类型将协定定义为一组已命名的公共成员。 实现 interface 的 class 或 struct 必须提供接口
成员的实现代码。 interface 可以继承自多个基接口, class 和 struct 可以实现多个接口。
delegate 类型表示引用包含特定参数列表和返回类型的方法。 通过委托,可以将方法视为可分配给变量并
可作为参数传递的实体。 委托类同于函数式语言提供的函数类型。 它们还类似于其他一些语言中存在的“函
数指针”概念。 与函数指针不同,委托是面向对象且类型安全的。
class 、 struct 、 interface 和 delegate 类型全部都支持泛型,因此可以使用其他类型对它们进行参数化。
C# 支持任意类型的一维和多维数组。 与上述类型不同,数组类型无需先声明即可使用。 相反,数组类型是通过
在类型名称后面添加方括号构造而成。 例如, int[] 是 int 类型的一维数组, int[,] 是 int 类型的二维数
组, int[][] 是由 int 类型的一维数组或“交错”数组构成的一维数组。
可以为 null 的类型不需要单独定义。 对于所有不可以为 null 的类型 T ,都有对应的可以为 null 的类型 T? ,后
者可以包含附加值 null 。 例如, int? 是可保存任何 32 位整数或 null 值的类型, string? 是可以保存任何
string 或 null 值的类型。
C# 采用统一的类型系统,因此任意类型的值都可视为 object 。 每种 C# 类型都直接或间接地派生自 object 类
类型,而 object 是所有类型的最终基类。 只需将值视为类型 object ,即可将引用类型的值视为对象。 通过执
行 装箱 和 取消装箱操作,可以将值类型的值视为对象。 在以下示例中, int 值被转换成 object ,然后又恢复
成 int 。
将值类型的值分配给 object 对象引用时,会分配一个“箱”来保存此值。 该箱是引用类型的实例,此值会被复制
到该箱。 相反,当 object 引用被显式转换成值类型时,将检查引用的 object 是否是具有正确值类型的箱。 如
果检查成功,则会将箱中的值复制到值类型。