首页 > 学院 > 开发设计 > 正文

C# Language Specification 5.0 (翻译)第四章 类型

2019-11-17 02:13:52
字体:
来源:转载
供稿:网友

C# Language Specification 5.0 (翻译)第四章 类型

C# Language Specification 5.0

C# 语言的类型分为两大类:值类型(value type)和引用类型(reference type),而它们又都同时具有至少一个类型形参的泛型类型(generic type)。类型形参(type parameters)能同时指定值类型和引用类型。

type

第三类是指针(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)。

value-type

与引用类型的变量不同,值类型的变量只有在类型是可空类型(nullable type)时才可以包含空值(null)。每一个非可空值类型(non-nullable value type)都有一个对应的可空值类型,它们具有相同的值集(只是额外再加上一个 null 值)。

对值类型变量的赋值会在赋值过程中创建一个值的副本。这与对一个引用类型变量赋值不同,引用类型只拷贝引用,而不是引用标识的对象。

System.ValueType 类型

所有值类型均隐式继承自 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):

  • 对于所有简单类型(simple-type)来说,默认值为所有位都为零的位模式(bit pattern of all zeros)产生的值:
  • 对于 sbyte, byte, short, ushort, int, uint, long, and ulong 来说,默认值为 0
  • 对于 char 来说,默认值为 '/x0000'
  • 对于 float 来说,默认值为 0.0f
  • 对于 double 来说,默认值为 0.0d
  • 对于 decimal 来说,默认值为 0.0m
  • 对于 bool 来说,默认值为 false
  • 对于枚举类型(enum-type)E 来说,默认值为 0,该值被转换为类型 E
  • 对于结构类型(struct-type)来说,默认值为通过设置其内所有值类型的值为其默认值、所有引用类型的值为 null 而产生的值;
  • 对于可空类型(nullable-type)来说,默认值为属性 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 命名空间内的结构类型提供了别名,如下表所示:

保留字别名对应的类型
sbyteSystem.SByte
byteSystem.Byte
shortSystem.Int16
ushortSystem.UInt16
intSystem.Int32
uintSystem.UInt32
longSystem.Int64
ulongSystem.UInt64
charSystem.Char
floatSystem.Single
doubleSystem.Double
boolSystem.Boolean
decimalSystem.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() 实例方法

简单类型与其它结构类型不同之处在于它们允许某些额外的操作:

  • 大部分简单类型允许通过书写字面值(literals)来创建值(第二章第 4.4 节)。比方说,123 是 int 类型的字面值,'a' 则是一个字符的字面值。C# 总体来说不对结构类型的字面值做过多规定,因此其它结构类型的非默认值(non-default values)总是通过这些结构类型的实例构造函数来创建。
  • 当表达式操作数都是些简单类型常量时,可能会使编译器在「编译时」对表达式进行计算。此种表达式叫做常量表达式(constant-exPRession,第七章第十九节)。由其他结构类型定义的表达式调用操作符不被视为常量表达式。
  • 通过 const 声明可在简单类型内声明一个常量(第十章第四节)。常量不可属于其它结构类型,但可使用静态只读字段(static readonly fields)达到相似目的。
  • 简单类型的转换调用可参与(participate)由其它结构类型所定义的转换操作符(conversion Operators)来计算,但用户定义转换操作符(user-defined conversion operator)永不可参与其它用户定义操作符之计算(第六章第 4.3 节)。

整数类型

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 被分类到整形,但它与其它整形在以下两处地方不同:

  • 不存在从其他类型到 char 类型的隐式转换。具体来讲,即便从 sbyte, byte 或 ushort 类型具有能完整地表示为 char 类型的取值范围,但它们也不能隐式地转换为 char 类型。
  • char 类型的常量必须被写为 character-literals 或带有(combination)强制转换类型(cast)为 char 的 integer-literals。比方说 (char)10'/x000A' 一样。

checkedunchecked 操作符和语句用于控制 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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表