1、版权所有 Microsoft Corporation 1999-2008。保留所有权利。请将更正、建议及其他反馈信息发送至 C#语言规范3.0 版版权所有 Microsoft Corporation 1999-2008。保留所有权利。注意 1999-2008 Microsoft Corporation。保留所有权利。Microsoft、 Windows、 Visual Basic、 Visual C# 和 Visual C+ 是 Microsoft Corporation 在美国和 /或其他国家 /地区的注册商标或商标。本文提及的其他产品和公司名称可能是其各自所有者的商标。目录版权所有 Mic
2、rosoft Corporation 1999-2008。保留所有权利。 iii目录1. 简介 .11.1 Hello world .11.2 程序结构 .21.3 类型和变量 .31.4 表达式 .61.5 语句 .81.6 类和对象 .121.6.1 成员 .121.6.2 可访问性 .131.6.3 类型形参 .131.6.4 基类 .141.6.5 字段 .141.6.6 方法 .151.6.6.1 参数 151.6.6.2 方法体和局部变量 161.6.6.3 静态方法和实例方法 171.6.6.4 虚方法、重写方法和抽象方法 181.6.6.5 方法重载 201.6.7 其他函数成
3、员 .211.6.7.1 构造函数 221.6.7.2 属性 231.6.7.3 索引器 231.6.7.4 事件 231.6.7.5 运算符 241.6.7.6 析构函数 251.7 结构 .251.8 数组 .261.9 接口 .271.10 枚举 .281.11 委托 .301.12 属性 .31C# 语言规范iv 版权所有 Microsoft Corporation 1999-2008。保留所有权利。2. 词法结构 .332.1 程序 .332.2 文法 .332.2.1 文法表示法 .332.2.2 词法文法 .342.2.3 句法文法 .342.3 词法分析 .342.3.1 行结
4、束符 .352.3.2 注释 .352.3.3 空白 .372.4 标记 .372.4.1 Unicode 字符转义序列 372.4.2 标识符 .382.4.3 关键字 .402.4.4 文本 .402.4.4.1 布尔值 402.4.4.2 整数 412.4.4.3 实数 422.4.4.4 字符 422.4.4.5 字符串 432.4.4.6 null 文本 .452.4.5 运算符和标点符号 .452.5 预处理指令 .452.5.1 条件编译符号 .472.5.2 预处理表达式 .472.5.3 声明指令 .482.5.4 条件编译指令 .492.5.5 诊断指令 .512.5.6
5、区域指令 .512.5.7 行指令 .522.5.8 Pragma 指令 .522.5.8.1 Pragma warning.53目录版权所有 Microsoft Corporation 1999-2008。保留所有权利。 v3. 基本概念 .553.1 应用程序启动 .553.2 应用程序终止 .563.3 声明 .563.4 成员 .583.4.1 命名空间成员 .583.4.2 结构成员 .583.4.3 枚举成员 .593.4.4 类成员 .593.4.5 接口成员 .593.4.6 数组成员 .593.4.7 委托成员 .593.5 成员访问 .603.5.1 已声明可访问性 .60
6、3.5.2 可访问域 .613.5.3 实例成员的受保护访问 .633.5.4 可访问性约束 .643.6 签名和重载 .653.7 范围 .663.7.1 名称隐藏 .683.7.1.1 通过嵌套隐藏 683.7.1.2 通过继承隐藏 693.8 命名空间和类型名称 .703.8.1 完全限定名 .723.9 自动内存管理 .733.10 执行顺序 .754. 类型 .774.1 值类型 .774.1.1 System.ValueType 类型 .784.1.2 默认构造函数 .784.1.3 结构类型 .794.1.4 简单类型 .79C# 语言规范vi 版权所有 Microsoft Co
7、rporation 1999-2008。保留所有权利。4.1.5 整型 .804.1.6 浮点型 .814.1.7 decimal 类型 .824.1.8 bool 类型 .824.1.9 枚举类型 .834.1.10 可以为 null 的类型 834.2 引用类型 .834.2.1 类类型 .844.2.2 对象类型 .854.2.3 string 类型 .854.2.4 接口类型 .854.2.5 数组类型 .854.2.6 委托类型 .854.3 装箱和拆箱 .854.3.1 装箱转换 .854.3.2 拆箱转换 .874.4 构造类型 .874.4.1 类型实参 .884.4.2 开放
8、和封闭类型 .884.4.3 绑定和未绑定类型 .894.4.4 满足约束 .894.5 类型形参 .904.6 表达式目录树类型 .915. 变量 .935.1 变量类别 .935.1.1 静态变量 .935.1.2 实例变量 .935.1.2.1 类中的实例变量 935.1.2.2 结构中的实例变量 945.1.3 数组元素 .945.1.4 值参数 .945.1.5 引用形参 .94目录版权所有 Microsoft Corporation 1999-2008。保留所有权利。 vii5.1.6 输出形参 .945.1.7 局部变量 .955.2 默认值 .955.3 明确赋值 .965.3
9、.1 初始已赋值变量 .965.3.2 初始未赋值变量 .975.3.3 确定明确赋值的细则 .975.3.3.1 一般语句规则 975.3.3.2 块语句、checked 和 unchecked 语句 985.3.3.3 表达式语句 985.3.3.4 声明语句 985.3.3.5 if 语句 .985.3.3.6 switch 语句 .995.3.3.7 while 语句 995.3.3.8 do 语句 .995.3.3.9 for 语句 995.3.3.10 break、continue 和 goto 语句 .1005.3.3.11 throw 语句 1005.3.3.12 return
10、 语句 .1005.3.3.13 try-catch 语句 .1005.3.3.14 try-finally 语句 .1005.3.3.15 try-catch-finally 语句 .1015.3.3.16 foreach 语句 .1025.3.3.17 using 语句 1025.3.3.18 lock 语句 1025.3.3.19 yield 语句 .1035.3.3.20 简单表达式的一般规则 1035.3.3.21 带有嵌入表达式的表达式的一般规则 1035.3.3.22 调用表达式和对象创建表达式 1035.3.3.23 简单赋值表达式 1045.3.3.24 class Hell
11、ostatic void Main() Console.WriteLine(“Hello, World“);C# 源文件的扩展名通常是 .cs。假定“Hello, World”程序存储在文件 hello.cs 中,可以使用下面的命令行调用 Microsoft C# 编译器编译这个程序:csc hello.csC# 语言规范2 版权所有 Microsoft Corporation 1999-2008。保留所有权利。编译后将产生一个名为 hello.exe 的可执行程序集。当此应用程序运行时,输出结果如下:Hello, World“Hello, World”程 序 的 开 头 是 一 个 usin
12、g 指 令 , 它 引 用 了 System 命 名 空 间 。 命 名 空 间 (namespace) 提 供 了 一 种 分 层 的 方 式 来 组 织 C# 程 序 和 库 。 命 名 空 间 中 包 含 有 类 型 及 其 他 命 名 空 间 例 如 , System 命 名 空 间 包 含 若 干 类 型 ( 如 此 程 序 中 引 用 的 Console 类 ) 以 及 若 干 其 他 命 名 空 间 ( 如 IO 和 Collections) 。 如果使用 using 指令引用了某一给定命名空间,就可以通过非限定方式使用作为命名空间成员的类型。在此程序中,正是由于使用了 usin
13、g 指令,我们可以使用 Console.WriteLine 这一简化形式代替完全限定方式 System.Console.WriteLine。“Hello, World”程序中声明的 Hello 类只有一个成员,即名为 Main 的方法。Main 方法是使用 static 修饰符声明的。实例 (instance) 方法可以使用关键字 this 来引用特定的封闭对象实例,而静态方法的操作不需要引用特定对象。按照惯例,名为 Main 的静态方法将作为程序的入口点。该程序的输出由 System 命名空间中的 Console 类的 WriteLine 方法产生。此类由 .NET Framework 类库
14、提供,默认情况下, Microsoft C# 编译器自动引用该类库。注意,C# 语言本身不具有单独的运行时库。事实上,.NET Framework 就是 C# 的运行时库。1.2 程序结构C# 中的组织结构的关键概念是程序 (program)、命名空间 (namespace)、类型 (type)、成员 (member) 和程序集 (assembly)。C# 程序由一个或多个源文件组成。程序中声明类型,类型包含成员,并且可按命名空间进行组织。类和接口就是类型的示例。字段 (field)、方法、属性和事件是成员的示例。在编译 C# 程序时,它们被物理地打包为程序集。程序集通常具有文件扩展名 .ex
15、e 或 .dll,具体取决于它们是实现应用程序 (application) 还是实现库 (library)。下面的示例using System;namespace Acme.Collectionspublic class StackEntry top;public void Push(object data) top = new Entry(top, data);public object Pop() if (top = null) throw new InvalidOperationException();object result = top.data;top = top.next;ret
16、urn result;class Entrypublic Entry next;public object data;public Entry(Entry next, object data) this.next = next;this.data = data;第 1 章 简介版权所有 Microsoft Corporation 1999-2008。保留所有权利。 3在名为 Acme.Collections 的命名空间中声明了一个名为 Stack 的类。这个类的完全限定名为 Acme.Collections.Stack。该类包含几个成员:一个名为 top 的字段,两个分别名为 Push 和 P
17、op 的方法和一个名为 Entry 的嵌套类。Entry 类还包含三个成员:一个名为 next 的字段,一个名为 data 的字段和一个构造函数。假定将此示例的源代码存储在文件 acme.cs 中,执行以下命令行:csc /t:library acme.cs将此示例编译为一个库(没有 Main 入口点的代码),并产生一个名为 acme.dll 的程序集。程序集包含中间语言 (Intermediate Language, IL) 指令形式的可执行代码和元数据 (metadata) 形式的符号信息。在执行程序集之前,.NET 公共语言运行库的实时 (JIT) 编译器将程序集中的 IL 代码自动转换
18、为特定于处理器的代码。由于程序集是一个自描述的功能单元,它既包含代码又包含元数据,因此,C# 中不需要 #include 指令和头文件。若要在 C# 程序中使用某特定程序集中包含的公共类型和成员,只需在编译程序时引用该程序集即可。例如,下面程序使用来自 acme.dll 程序集的 Acme.Collections.Stack 类:using System;using Acme.Collections;class Teststatic void Main() Stack s = new Stack();s.Push(1);s.Push(10);s.Push(100);Console.WriteL
19、ine(s.Pop();Console.WriteLine(s.Pop();Console.WriteLine(s.Pop();如果此程序存储在文件 test.cs 中,那么在编译 test.cs 时,可以使用编译器的 /r 选项引用 acme.dll 程序集:csc /r:acme.dll test.cs这样将创建名为 test.exe 的可执行程序集,运行结果如下:100101C# 允许将一个程序的源文本存储在多个源文件中。在编译多个文件组成的 C# 程序时,所有源文件将一起处理,并且源文件可以自由地相互引用 从概念上讲,就像是在处理之前将所有源文件合并为一个大文件。C# 中从不需要前向声
20、明,因为除了极少数的例外情况,声明顺序无关紧要。C# 不限制一个源文件只能声明一个公共类型,也不要求源文件的名称与该源文件中声明的类型匹配。1.3 类型和变量C# 中的类型有两种:值类型 (value type) 和引用类型 (reference type)。值类型的变量直接包含它们的数据,而引用类型的变量存储对它们的数据的引用,后者称为对象。对于引用类型,两个变量可能引用同一个对象,因此对一个变量的操作可能影响另一个变量所引用的对象。对于值类型,每个变量都有它们自己的数据副本(除 ref 和 out 参数变量外),因此对一个变量的操作不可能影响另一个变量。C# 的值类型进一步划分为简单类型
21、(simple type)、枚举类型 (enum type)、结构类型 (struct type) 和可以为 null 的类型 (nullable type),C# 的引用类型进一步划分为类类型 (class type)、接口类型 (interface type)、数组类型 (array type) 和委托类型 (delegate type)。C# 语言规范4 版权所有 Microsoft Corporation 1999-2008。保留所有权利。下表为 C# 类型系统的概述。类别 说明有符号整型:sbyte、short、int 和 long无符号整型:byte、ushort、uint 和 u
22、longUnicode 字符型:charIEEE 浮点型:float 和 double高精度小数型:decimal简单类型布尔型:bool枚举类型 enum E . 形式的用户定义的类型结构类型 struct S . 形式的用户定义的类型值类型可以为 null 的类型其他所有具有 null 值的值类型的扩展其他所有类型的最终基类:objectUnicode 字符串型:string类类型class C . 形式的用户定义的类型接口类型 interface I . 形式的用户定义的类型数组类型 一维和多维数组,例如 int 和 int,引用类型委托类型 例如,delegate int D(.) 形
23、式的用户定义的类型八种整型类型分别支持 8 位、16 位、32 位和 64 位整数值的有符号和无符号的形式。两种浮点类型:float 和 double,分别使用 32 位单精度和 64 位双精度的 IEEE 754 格式表示。decimal 类型是 128 位的数据类型,适合用于财务计算和货币计算。C# 的 bool 类型用于表示布尔值 为 true 或者 false 的值。在 C# 中,字符和字符串处理使用 Unicode 编码。char 类型表示一个 UTF-16 编码单元,string 类型表示 UTF-16 编码单元的序列。下表总结了 C# 的数值类型。第 1 章 简介版权所有 Mic
24、rosoft Corporation 1999-2008。保留所有权利。 5类别 位数 类型 范围/精度8 sbyte 128 至 12716 short 32,768 至 32,76732 int 2,147,483,648 至 2,147,483,647有符号整型64 long 9,223,372,036,854,775,808 至 9,223,372,036,854,775,8078 byte 0 至 25516 ushort 0 至 65,53532 uint 0 至 4,294,967,295无符号整型64 ulong 0 至 18,446,744,073,709,551,61532
25、 float 1.5 1045 至 3.4 1038,7 位精度浮点型64 double 5.0 10324 至 1.7 10308,15 位精度小数 128 decimal 1.0 1028 至 7.9 1028,28 位精度C# 程序使用类型声明 (type declaration) 创建新类型。类型声明指定新类型的名称和成员。在 C# 类型分类中,有五类是用户可定义的:类类型 (class type)、结构类型 (struct type)、接口类型 (interface type)、枚举类型 (enum type) 和委托类型 (delegate type)。类类型定义了一个包含数据成员
26、(字段)和函数成员(方法、属性等)的数据结构。类类型支持单一继承和多态,这些是派生类可用来扩展和专用化基类的机制。结 构 类 型 与 类 类 型 相 似 , 表 示 一 个 带 有 数 据 成 员 和 函 数 成 员 的 结 构 。 但 是 , 与 类 不 同 , 结 构 是 一 种 值 类型 , 并 且 不 需 要 堆 分 配 。 结 构 类 型 不 支 持 用 户 指 定 的 继 承 , 并 且 所 有 结 构 类 型 都 隐 式 地 从 类 型 object 继 承 。接口类型定义了一个协定,作为一个公共函数成员的命名集。实现某个接口的类或结构必须提供该接口的函数成员的实现。一个接口可以
27、从多个基接口继承,而一个类或结构可以实现多个接口。委托类型表示对具有特定参数列表和返回类型的方法的引用。通过委托,我们能够将方法作为实体赋值给变量和作为参数传递。委托类似于在其他某些语言中的函数指针的概念,但是与函数指针不同,委托是面向对象的,并且是类型安全的。类类型、结构类型、接口类型和委托类型都支持泛型,因此可以通过其他类型将其参数化。枚举类型是具有命名常量的独特的类型。每种枚举类型都具有一个基础类型,该基础类型必须是八种整型之一。枚举类型的值集和它的基础类型的值集相同。C# 支持由任何类型组成的一维和多维数组。与以上列出的类型不同,数组类型不必声明就可以使用。实际上,数组类型是通过在某个
28、类型名后加一对方括号来构造的。例如,int 是一维 int 数组,int, 是二维 int 数组,int 是一维 int 数组的一维数组。可以为 null 的类型也不必声明就可以使用。对于每个不可以为 null 的值类型 T,都有一个相应的可以为 null 的类型 T?,该类型可以容纳附加值 null。例如,int? 类型可以容纳任何 32 位整数或 null 值。C# 语言规范6 版权所有 Microsoft Corporation 1999-2008。保留所有权利。C# 的类型系统是统一的,因此任何类型的值都可以按对象处理。C# 中的每个类型都直接或间接地从 object 类类型派生,而
29、object 是所有类型的最终基类。引用类型的值都被当作 “对象”来处理,因为这些值可以简单地视为属于 object 类型。值类型的值则是在对其执行装箱 (boxing) 和拆箱 (unboxing) 操作后按对象处理。下面的示例将 int 值转换为 object,然后又转换回 int。using System;class Teststatic void Main() int i = 123;object o = i; / Boxingint j = (int)o; / Unboxing当将值类型的值转换为类型 object 时,将分配一个对象实例(也称为 “箱子”)以包含该值,并将值复制到该
30、箱子中。反过来,当将一个 object 引用强制转换为值类型时,将检查所引用的对象是否含有正确的值类型,如果有,则将箱子中的值复制出来。C# 的统一类型系统实际上意味着值类型可以“按需”转换为对象。因为统一,所以使用类型 object 的通用库可以与引用类型和值类型一同使用。C# 中存在几种变量 (variable),包括字段、数组元素、局部变量和参数。变量表示存储位置,并且每个变量都有一个类型,以决定什么样的值能够存入变量,如下表所示。变量类型 可能的内容不可以为 null 的值类型类型完全相同的值可以为 null 的值类型null 值或类型完全相同的值对象 空引用、对任何引用类型的对象的引
31、用,或者对任何值类型的装箱值的引用类类型 空引用、对该类类型的实例的引用,或者对从该类类型派生的类的实例的引用接口类型 空引用、对实现该接口类型的类类型的实例的引用,或者对实现该接口类型的值类型的装箱值的引用数组类型 空引用、对该数组类型的实例的引用,或者对兼容数组类型的实例的引用委托类型 空引用或对该委托类型的实例的引用1.4 表达式表达式 (expression) 由操作数 (operand) 和运算符 (operator) 构成。表达式的运算符指示对操作数应用什么样的运算。运算符的示例包括 +、- 、*、/ 和 new。操作数的示例包括文本 (literal)、字段、局部变量和表达式。第
32、 1 章 简介版权所有 Microsoft Corporation 1999-2008。保留所有权利。 7当表达式包含多个运算符时,运算符的优先级 (precedence) 控制各运算符的计算顺序。例如,表达式 x + y * z 按 x + (y * z) 计算,因为 * 运算符的优先级高于 + 运算符。大多数运算符都可以重载 (overload)。运算符重载允许指定用户定义的运算符实现来执行运算,这些运算的操作数中至少有一个,甚至所有操作数都属于用户定义的类类型或结构类型。下 表 总 结 了 C# 运 算 符 , 并 按 优 先 级 从 高 到 低 的 顺 序 列 出 各 运 算 符 类
33、别 。 同 一 类 别 中 的 运 算 符 优 先 级 相同 。类别 表达式 说明x.m 成员访问x(.) 方法和委托调用x. 数组和索引器访问x+ 后增量x- 后减量new T(.) 对象和委托创建new T(.). 使用初始值设定项创建对象new . 匿名对象初始值设定项new T. 数组创建typeof(T) 获得 T 的 System.Type 对象checked(x) 在 checked 上下文中计算表达式unchecked(x) 在 unchecked 上下文中计算表达式default(T) 获取类型 T 的默认值基本delegate . 匿名函数(匿名方法)+x 恒等-x 求相反
34、数!x 逻辑求反x 按位求反+x 前增量-x 前减量一元(T)x 将 x 显式转换为类型 Tx * y 乘法x / y 除法乘除x % y 求余C# 语言规范8 版权所有 Microsoft Corporation 1999-2008。保留所有权利。x + y 加法、字符串串联、委托组合加减x y 减法、委托移除x y 右移x y 大于x = y 大于或等于x is T 如果 x 属于 T 类型,则返回 true ,否则返回 false关系和类型检测x as T 返回转换为类型 T 的 x,如果 x 不是 T 则返回 nullx = y 等于相等x != y 不等于逻辑 AND x & y 整
35、型按位 AND,布尔逻辑 AND逻辑 XOR x y 整型按位 XOR,布尔逻辑 XOR逻辑 OR x | y 整型按位 OR,布尔逻辑 OR条件 AND x & y 仅当 x 为 true 才对 y 求值条件 OR x | y 仅当 x 为 false 才对 y 求值空合并 X ? y 如果 x 为 null,则对 y 求值,否则对 x 求值条件 x ? y : z 如果 x 为 true,则对 y 求值,如果 x 为 false,则对 z 求值x = y 赋值x op= y 复合赋值;支持的运算符有:*= /= %= += -= = &= = |=赋值或匿名函数(T x) = y 匿名函数(lambda 表达式)1.5 语句程 序 的 操 作 是 使 用 语 句 (statement) 来 表 示 的 。 C# 支 持 几 种 不 同 的 语 句 , 其 中 许 多 以 嵌 入 语 句 的 形 式 定义 。块 (block) 用于在只允许使用单个语句的上下文中编写多条语句。块由位于一对大括号 和 之间的语句列表组成。声明语句 (declaration statement) 用于声明局部变量和常量。