一/值类型
1/整型
- C# 支持 9 种整型:sbyte、byte、short、ushort、int、uint、long、ulong 和 char。整型具有以下所列的大小和取值范围:
- sbyte 类型表示有符号 8 位整数,其值介于 -128 和 127 之间。
- byte 类型表示无符号 8 位整数,其值介于 0 和 255 之间。
- short 类型表示有符号 16 位整数,其值介于 -32768 和 32767 之间。
- ushort 类型表示无符号 16 位整数,其值介于 0 和 65535 之间。
- int 类型表示有符号 32 位整数,其值介于 -2147483648 和 2147483647 之间。
- uint 类型表示无符号 32 位整数,其值介于 0 和 4294967295 之间。
- long 类型表示有符号 64 位整数,其值介于 -9223372036854775808 和 9223372036854775807 之间。
- ulong 类型表示无符号 64 位整数,其值介于 0 和 18446744073709551615 之间。
- char 类型表示无符号 16 位整数,其值介于 0 和 65535 之间。char 类型的可能值集与 Unicode 字符集相对应。虽然 char 的表示形式与 ushort 相同,但是可以对一种类型进行的所有计算并非都可以对另一种类型执行。
整型一元运算符和二元运算符总是对有符号 32 位精度、无符号的 32 位精度、有符号 64 位精度或无符号 64 位精度进行计算:
- 对于一元运算符 + 和 ~,操作数转换为 T 类型,其中 T 是 int、uint、long 和 ulong 中第一个可以完全表示操作数的所有可能值的类型。然后用 T 类型的精度执行运算,结果的类型是 T 类型。
- 对于一元运算符 –,操作数转换为类型 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 类型归类为整型类型,但它在以下两个方面不同于其他整型:
- 不存在从其他类型到 char 类型的隐式转换。具体而言,即使 sbyte、byte 和 ushort 类型具有完全可以用 char 类型来表示的值范围,也不存在从 sbyte、byte 或 ushort 到 char 的隐式转换。
- char 类型的常量必须写成 character-literal 或带有强制转换为类型 char 的 integer-literal。例如,(char)10 与 ‘\x000A‘ 是相同的。
checked 和 unchecked 运算符和语句用于控制整型算术运算和转换的溢出检查。在 checked 上下文中,溢出产生编译时错误或导致引发 System.OverflowException。在 unchecked 上下文中将忽略溢出,任何与目标类型不匹配的高序位都被放弃。
2/浮点型
C# 支持两种浮点型:float 和 double。float 和 double 类型用 32 位单精度和 64 位双精度 IEEE 754 格式来表示,这些格式提供以下几组值:
- 正零和负零。大多数情况下,正零和负零的行为与简单的值零相同,但某些运算会区别对待此两种零。
- 正无穷大和负无穷大。无穷大是由非零数字被零除这样的运算产生的。例如,1.0 / 0.0 产生正无穷大,而 –1.0 / 0.0 产生负无穷大。
- 非数字 (Not-a-Number) 值,常缩写为 NaN。NaN 是由无效的浮点运算(如零被零除)产生的。
- 以 s × m × 2e 形式表示的非零值的有限集,其中 s 为 1 或 ?1,m 和 e 由特殊的浮点类型确定:对于 float,为 0 < m < 224并且 ?149 ≤ e ≤ 104;对于 double,为 0 < m < 253 并且 ?1075 ≤ e ≤ 970。非标准化的浮点数被视为有效非零值。
float 类型可表示精度为 7 位、在大约 1.5 × 10?45 到 3.4 × 1038 的范围内的值。
double 类型可表示精度为 15 位或 16 位、在大约 5.0 × 10?324 到 1.7 × 10308 的范围内的值。
如果二元运算符的一个操作数为浮点型,则另一个操作数必须为整型或浮点型,并且运算按下面这样计算:
- 如果一个操作数为整型,则该操作数转换为与另一个操作数的类型相同的浮点型。
- 然后,如果任一操作数的类型为 double,则另一个操作数转换为 double。至少用 double 范围和精度执行运算,结果的类型为 double(对于关系运算符则为 bool)。
- 否则,至少用 float 范围和精度执行运算,结果的类型为 float(对于关系运算符则为 bool)。
浮点运算符(包括赋值运算符)从来不产生异常。相反,在异常情况下,浮点运算产生零、无穷大或 NaN,如下所述:
- 如果浮点运算的结果对于目标格式太小,则运算结果变成正零或负零。
- 如果浮点运算的结果对于目标格式太大,则运算结果变成正无穷大或负无穷大。
- 如果浮点运算无效,则运算的结果变成 NaN。
- 如果浮点运算的一个或两个操作数为 NaN,则运算的结果变成 NaN。
可以用比运算的结果类型更高的精度来执行浮点运算。例如,某些硬件结构支持比 double 类型具有更大的范围和精度的“extended”或“long double”浮点型,并隐式地使用这种更高精度类型执行所有浮点运算。只有性能开销过大,才能使这样的硬件结构用“较低”的精度执行浮点运算。C# 采取的是允许将更高的精度类型用于所有浮点运算,而不是强求执行规定的精度,造成同时损失性能和精度。除了传递更精确的结果外,这样做很少会产生任何可察觉的效果。但是,在 x * y / z 形式的表达式中,如果其中的乘法会产生超出 double 范围的结果,而后面的除法使临时结果返回到 double 范围内,则以更大范围的格式去计算该表达式,可能会产生有限值的结果(本来应是无穷大)。
3/decimal 类型
decimal 类型是 128 位的数据类型,适合用于财务计算和货币计算。decimal 类型可以表示具有 28 或 29 个有效数字、从 1.0 × 10?28 到大约 7.9 × 1028 范围内的值。
decimal 类型的有限值集的形式为 (–1)s × c × 10-e,其中符号 s 是 0 或 1,系数 c 由 0 ≤ c < 296 给定,小数位数 e 满足 0 ≤ e ≤ 28。decimal 类型不支持有符号的零、无穷大或 NaN。decimal 可用一个以 10 的幂表示的 96 位整数来表示。对于绝对值小于 1.0m 的 decimal,它的值最多精确到第 28 位小数。对于绝对值大于或等于 1.0m 的 decimal,它的值精确到小数点后第 28 或 29 位。与 float 和 double 数据类型相反,十进制小数数字(如 0.1)可以精确地用 decimal 表示形式来表示。在 float 和 double 表示形式中,这类数字通常变成无限小数,使这些表示形式更容易发生舍入错误。
如果二元运算符的一个操作数为 decimal 类型,则另一个操作数必须为整型或 decimal 类型。如果存在一个整型操作数,它将在执行运算前转换为 decimal。
decimal 类型值的运算结果是这样得出的:先计算一个精确结果(按每个运算符的定义保留小数位数),然后舍入以适合表示形式。结果舍入到最接近的可表示值,当结果同样地接近于两个可表示值时,舍入到最小有效位数位置中为偶数的值(这称为“银行家舍入法”)。零结果总是包含符号 0 和小数位数 0。
如果十进制算术运算产生一个绝对值小于或等于 5 × 10-29 的值,则运算结果变为零。如果 decimal 算术运算产生的值对于 decimal 格式太大,则将引发 System.OverflowException。
与浮点型相比,decimal 类型具有较高的精度,但取值范围较小。因此,从浮点型到 decimal 的转换可能会产生溢出异常,而从 decimal 到浮点型的转换则可能导致精度损失。由于这些原因,在浮点型和 decimal 之间不存在隐式转换,如果没有显式地标出强制转换,就不可能在同一表达式中同时使用浮点操作数和 decimal 操作数。
4/bool类型
bool 类型表示布尔逻辑量。bool 类型的可能值为 true 和 false。
在 bool 和其他类型之间不存在标准转换。具体而言,bool 类型与整型截然不同,不能用 bool 值代替整数值,反之亦然。
在 C 和 C++ 语言中,零整数或浮点值或 null 指针可以转换为布尔值 false,非零整数或浮点值或非 null 指针可以转换为布尔值 true。在 C# 中,这种转换是通过显式地将整数或浮点值与零进行比较,或者显式地将对象引用与 null 进行比较来完成的。
5/枚举类型
枚举类型是具有命名常量的独特的类型。每个枚举类型都有一个基础类型,该基础类型必须为 byte、sbyte、short、ushort、int、uint、long 或 ulong。枚举类型的值集和它的基础类型的值集相同。枚举类型的值并不只限于那些命名常量的值。枚举类型是通过枚举声明定义的。