C# 语言的类型分为两大类:值类型(value type)和引用类型(reference type),而它们又都同时具有至少一个类型形参的泛型类型(generic type)。类型形参(type parameters)能同时指定值类型和引用类型。
第三类是指针(pointers),只能用于非安全代码(unsafe code)中。关于非安全代码,将在第十八章第二节内讨论。
值类型与引用类型不同之处在于值类型的变量直接包含其数据,而引用类型的变量保存对其数据的引用(references),后者被称为对象(objects)。对于引用类型,可能两个变量能引用同一个对象,也可能因操作一个变量所引用的对象而影响到其它变量。对于值类型,每个变量都拥其数据之副本,不会因操作其一而影响其它。
C# 的类型系统拥有统一标准,任何类型的值都能被当做对象来处理(a value of any type can be treated as an object)。C# 中每种类型都直接或间接派生自 object
类类型,object
是所有类型的最终基类(ultimate base class)。引用类型的值都被视为 object
类型故被简单当做对象来处理。值类型的值通过装箱与拆箱操作来实现类型处理(第四章第三节)。
值类型(value type)可以是一个结构类型(struct type),也可以是一个枚举类型(enumeration type)。C# 提供了一组预定义的结构类型,称作简单类型(simple types)。简单类型通过保留字(reserved Words)[1]标识(identified)。
与引用类型的变量不同,值类型的变量只有在类型是可空类型(nullable type)时才可以包含空值(null)。每一个非可空值类型(non-nullable value type)都有一个对应的可空值类型,它们具有相同的值集(只是额外再加上一个 null 值)。
对值类型变量的赋值会在赋值过程中创建一个值的副本。这与对一个引用类型变量赋值不同,引用类型只拷贝引用,而不是引用标识的对象。
所有值类型均隐式继承自 System.ValueType
类,后者又继承自 object
类。不可能对值类型进行派生,值类型都隐式密封(implicitly sealed,第十章第 1.1.2 节)的。
注意,System.ValueType
自身并不是值类型(value-type)。确切地讲,它是一个类类型(class-type),所有的值类型(value-type)都自动派生自它。
所有值类型均隐式声明了一个公共无参实例构造函数(public parameterless instance constructor),称作默认构造函数(default constructor)。默认构造函数返回一个零初始化实例(zero-initialized instance),它就是值类型的默认值(default value):
0
;'/x0000'
;0.0f
;0.0d
;0.0m
;false
。E
来说,默认值为 0
,该值被转换为类型 E
;HasValue
为 false 且属性 value
未定义的(undefined)的实例。默认值也可以叫做可空值类型的 null 值(null value)。和其它实例构造函数一样,值类型的默认构造函数也通过 new
操作符来调用。出于效率的缘故,实际上我们不必去执行调用它的构造函数。在下例中,变量 i 和 j 都会初始化为零(zero)。
class A{ void F() { int i = 0; int j = new int(); }}
因为每个值类型都隐式拥有一个公开无参实例构造函数,所以结构类型中不可以显式包含一个无参构造函数的声明,但允许结构类型声明参数化实例构造函数(parameterized instance constructors,第十一章第 3.8 节)。
结构类型(struct type)是能声明常量、字段、方法、属性、索引器、操作符、实例构造函数、静态构造函数和嵌套类型的值类型。构造类型的声明在第十一章第一节中有描述。
C# 提供了一组预定义的结构类型,称作简单类型(simple type)。简单类型通过保留字进行识别,但这些保留字也只是简单地为预定义于 System
命名空间内的结构类型提供了别名,如下表所示:
保留字 | 别名对应的类型 |
---|---|
sbyte | System.SByte |
byte | System.Byte |
short | System.Int16 |
ushort | System.UInt16 |
int | System.Int32 |
uint | System.UInt32 |
long | System.Int64 |
ulong | System.UInt64 |
char | System.Char |
float | System.Single |
double | System.Double |
bool | System.Boolean |
decimal | System.Decimal |
由于简单类型是结构类型的别名,故每一个简单类型都有成员。比方说 int
有声明于 System.Int32
内的成员以及继承自 System.Object
的成员,下面这些语句是合法的:
int i = int.MaxValue; // System.Int32.MaxValue 常量string s = i.ToString(); // System.Int32.ToString() 实例方法string t = 123.ToString(); // System.Int32.ToString() 实例方法
简单类型与其它结构类型不同之处在于它们允许某些额外的操作:
123
是 int 类型的字面值,'a'
则是一个字符的字面值。C# 总体来说不对结构类型的字面值做过多规定,因此其它结构类型的非默认值(non-default values)总是通过这些结构类型的实例构造函数来创建。const
声明可在简单类型内声明一个常量(第十章第四节)。常量不可属于其它结构类型,但可使用静态只读字段(static readonly fields)达到相似目的。C# 支持九中整数类型(integral type):sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
以及 char
。整数类型值的尺寸与范围如下:
sbyte
类型表示有符号(signed)的 8 位(8-bit)整数,区间为 -128 到 127;byte
类型表示无符号(unsigned)的 8 位(8-bit)整数,区间为 0 到 255;short
类型表示有符号的 16 位(16-bit)整数,区间为 -32768 到 32767;ushort
类型表示无符号的 16 位(16-bit)整数,区间为 0 到 65535;int
类型表示有符号的 32 位(32-bit)整数,区间为 -2147483648 到 2147483647;uint
类型表示无符号的 32 位(32-bit)整数,区间为 0 到 4294967295;long
类型表示有符号的 64 位(64-bit)整数,区间为 –9223372036854775808 到 9223372036854775807;ulong
类型表示无符号的 64 位(64-bit)整数,区间为 0 到 18446744073709551615;char
类型表示无符号的 16(16-bit)位整数,区间为 0 到 65535。其字符类型的取值范围符合 Unicode 字符集。尽管 char 字符表现形式与 ushort 一样,但对其中一种类型进行的所有操作不一定可以对另一种类型进行。整数类型的一元操作符(unary operator)和二元操作符(binary operator)可以操作有符号 32 位精度(precision)、无符号 32 位精度、有符号 64 位精度和无符号 64 位精度的操作数:
+
和 ~
,操作数(operand)会被转换为类型 T,其中 T 为 int, uint, long 或 ulong 中首个可完全表示操作数所有可能值的类型,而后用类型 T 的精度进行计算,其结果为 T 类型的。-
,操作数(operand)会被转换为类型 T,其中 T 为 int, long 中首个可完全表示操作数所有可能值的类型,然后在 T 类型的精度下进行计算,其结果为 T 类型。一元操作符 -
不支持 ulong 操作数。+
、 -
、 *
、 /
、 %
、 &
、 ^
、 |
、 ==
、 !=
、 >
、 <
、 >=
以及 <=
,操作数会被转换为类型 T,其中 T 是 int, uint, long 或 ulong 中首个可完全表示两个操作数所有可能值的类型,然后在 T 类型的精度下进行计算,其结果为 T 类型(如果是关系操作符,则返回 bool
)。二元操作符不允许一个操作数是 long 而另一个操作数是 ulong。<<
和 >>
,左操作数被转换为类型 T,其中 T 为 int, uint, long 或 ulong 中首个可完全表示操作数的所有可能值的类型,而后用类型 T 的精度执行运算,其结果是 T 类型的。虽然 char
被分类到整形,但它与其它整形在以下两处地方不同:
character-literals
或带有(combination)强制转换类型(cast)为 char 的 integer-literals
。比方说 (char)10
和 '/x000A'
一样。checked
和 unchecked
操作符和语句用于控制 integral-type
算术运算(arithmetic operations)与转换(conversions,第七章第 6.12 节)的溢出检查(overflow checking)。在 checked
上下文(context)中,溢出会导致「编译时错误」或导致一个 System.OverflowException
异常被抛出。在 unchecked
上下文中,溢出会被忽略(ignored),并且所有与目标类型(destination type)不匹配(not fit)的高位(high-order bits)都会被丢弃。
C# 支持两种浮点数(floating-point)类型:float 和 double。float 和 double 类型表示为使用 32
新闻热点
疑难解答