购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.11 语句

函数是由语句构成的。语句按照出现的字面顺序执行。语句块则是包含在大括号( {} )中的一系列语句。

2.11.1 声明语句

变量声明语句可以声明新的变量,并可以用表达式初始化变量。我们可以用逗号分隔的列表声明多个同类型的变量:

常量的声明和变量类似,但是它的值无法在声明之后改变,并且变量初始化必须和声明同时进行(请参见3.1.2节):

局部变量

局部变量和常量的作用范围在当前的语句块中。在当前语句块或者嵌套的语句块中无法声明同名的局部变量:

变量的作用范围是其所在的整个代码块(包括前向和后向)。这意味着虽然在变量或常量声明之前引用它是不合法的,但即使将示例中的 x 初始化移动到方法的末尾我们也会得到相同的错误,这个奇怪的规则和C++是不同的。

2.11.2 表达式语句

表达式语句既是表达式也是合法的语句。表达式语句必须改变状态或者执行某些可能改变状态的调用。状态改变本质上指改变一个变量的值。可能的表达式语句有:

· 赋值表达式(包括自增和自减表达式)

· (有返回值的和没有返回值的)方法调用表达式

· 对象实例化表达式

例如:

即使调用的构造器或方法有返回值,也并不一定要使用该值。因此除非构造器或方法改变了某些状态,否则以下这些语句完全没有用处:

2.11.3 选择语句

C#使用以下几种机制来有条件地控制程序的执行流:

· 选择语句( if switch

· 条件语句( ?:

· 循环语句( while do..while for foreach

本节将介绍两种最简单的结构: if 语句和 switch 语句。

2.11.3.1 if语句

if 语句在bool表达式为真时执行其中的语句,例如:

if 中的语句可以是代码块:

2.11.3.2 else子句

if 语句之后可以紧跟 else 子句:

else 子句中,能嵌套另一个 if 语句:

2.11.3.3 用大括号改变执行流

else 子句总是与它之前的语句块中紧邻的未配对的 if 语句结合:

语义上等价于:

可以通过改变大括号的位置来改变执行流:

大括号可以明确表明结构,这能提高嵌套 if 语句的可读性(虽然编译器并不需要)。需要特别指出的是下面的模式:

这里,我们参照其他语言的“elseif”结构(以及C#本身的 #elif 预处理指令)来安排 if else 语句。Visual Studio会自动识别这个模式并保持代码缩进。从语义上讲,紧跟着每一个 if 语句的 else 语句从功能上都是嵌套在 else 子句之中的。

2.11.3.4 switch语句

switch 语句可以根据变量可能的取值来转移程序的执行。 switch 语句可以拥有比嵌套 if 语句更加简洁的代码,因为 switch 语句仅仅需要一次表达式计算:

这个例子演示了最一般的情形,即针对常量的switch。当指定常量时,只能指定内置的整数类型、 bool char enum 类型以及 string 类型。

每一个 case 子句结束时必须使用某种跳转指令显式指定下一个执行点(除非你的代码本身就是一个无限循环),这些跳转指令有:

· break (跳转到 switch 语句的最后)

· goto case x (跳转到另外一个 case 子句)

· goto default (跳转到 default 子句)

· 其他的跳转语句,例如, return throw continue 或者 goto label

当多个值需要执行相同的代码时,可以按照顺序列出共同的 case 条件:

switch 语句的这种特性可以写出比多个 if-else 更加简洁的代码。

2.11.3.5 按类型switch

按照类型进行switch是带有模式的 switch 语句的一种特殊的使用情况,最近几版C#语言引入了多种模式。有关模式的完整讨论,请参见4.13节。

C#支持按类型switch(从C# 7开始):

object 类型允许其变量为任何类型,这部分内容将在3.2节和3.3节详细讨论。)

每一个 case 子句都指定了一种需要匹配的类型和一个变量(模式变量),如果类型匹配成功就对变量赋值。和常量不同,子句对可用的类型并没有进行任何限制。

when 关键字可用于对 case 进行预测,例如:

case 子句的顺序会影响类型的选择(这和选择常量的情况有些不同)。如果交换case的顺序,则上述示例可以得到完全不同的结果(事实上,上述程序甚至无法编译,因为编译器发现第二个 case 子句是永远不会执行的)。但 default 子句是一个例外,不论它出现在什么地方都会在最后才执行。

如果希望按照类型进行 switch ,但对其值却并不关心,这种情况下可以使用“丢弃”变量(_):

堆叠多个 case 子句也是没有问题的。在下面的例子中, Console.WriteLine 会在任何浮点类型的值大于1000时执行:

在上述例子中,编译器仅允许在 when 子句中使用模式变量 f d m 。当调用 Console.WriteLine 时,我们并不清楚到底三个模式变量中的哪一个会被赋值,因而编译器会将它们放在作用域之外。

除此以外,还可以混合使用常量选择和模式选择,甚至可以选择null值:

2.11.3.6 switch表达式

从C# 8开始,我们可以在表达式中使用 switch 。以下示例展示了该功能的使用方法,其中,假定变量 cardNumber int 类型:

注意, switch 是在变量名称之后出现的,且其中的 case 子句相应地变为了以逗号结尾的表达式(而不再是语句)。 switch 表达式相比 switch 语句更加紧凑,且可以用于LINQ查询(请参见第8章)。

如果在 switch 表达式中忽略默认表达式(_)同时其他条件匹配失败,则会抛出一个异常。

switch 表达式也支持多变量的选择(元组模式):

switch 表达式与各种模式组合可以获得更多的选择效果,详情请参见4.13节。

2.11.4 迭代语句

C#中可以使用 while do-while for foreach 语句重复执行一系列语句。

2.11.4.1 while和do-while循环

while 循环在 bool 表达式为true的情况下重复执行循环体中的代码。该表达式在循环体执行之前进行检测。例如,以下示例将输出 012

do-while 循环在功能上不同于 while 循环的地方是前者在语句块执行之后才检查表达式的值(保证语句块至少执行过一次)。以下是用 do-while 循环重新书写上述例子:

2.11.4.2 for循环

for 循环就像一个有特殊子句的 while 循环,这些特殊子句用于初始化和迭代循环变量。 for 循环有以下三个子句:

每一个子句的作用如下:

初始化子句

在循环之前执行,初始化一个或多个迭代变量。

条件子句

它是一个 bool 表达式,当取值为true时,将执行循环体。

迭代子句

在每次语句块迭代之后执行,通常用于更新迭代变量。

例如,下面的例子将输出0到2的数字:

下面的代码将输出前10个斐波那契数(每一个数都是前面两个数的和):

for 语句的这三个部分都可以省略,因而可以通过下面的代码来实现无限循环(也可以用 while(true) 来代替):

2.11.4.3 foreach循环

foreach 语句遍历可枚举对象的每一个元素,.NET中大多数表示集合或元素列表的类型都是可枚举的。例如,数组和字符串都是可枚举的。以下示例从头到尾枚举了字符串中的每一个字符:

以上程序的输出为:

我们将在4.6节详细介绍可枚举对象。

2.11.5 跳转语句

C#的跳转语句有 break continue goto return throw

跳转语句仍然遵守 try 语句的可靠性规则(参见4.5节),因此:

· 若跳转语句跳转到 try 语句块之外,则它总是在达到目标之前执行 try 语句的 finally 语句块。

· 跳转语句不能从 finally 语句块内跳到块外(除非使用 throw )。

2.11.5.1 break语句

break 语句用于结束迭代或 switch 语句的执行:

2.11.5.2 continue语句

continue 语句放弃循环体中后续的语句,继续下一轮迭代。例如,以下的循环跳过了偶数:

2.11.5.3 goto语句

goto 语句将执行点转移到语句块中的指定标签处,格式如下:

或用于 switch 语句内:

标签语句仅仅是代码块中的占位符,位于语句之前,用冒号后缀表示。下面的代码模拟 for 循环来遍历从 1 5 的数字:

goto case case-constant 会将执行点转移到 switch 语句块中的另一个条件上(参见2.11.3.4节)。

2.11.5.4 return语句

return 语句用于退出方法。如果这个方法有返回值,则必须返回方法指定返回类型的表达式。

return 语句能够出现在方法的任意位置(除 finally 块中),并且可以多次出现。

2.11.5.5 throw语句

throw 语句抛出异常来表示有错误发生(参见4.5节):

2.11.6 其他语句

using 语句用一种优雅的语法在 finally 块中调用实现了 IDisposable 接口对象的 Dispose 方法(请参见4.5节和12.1节)。

C#重载了 using 关键字,使它在不同上下文中有不同的含义。特别地, using 指令和 using 语句是不同的。

lock 语句是调用 Mintor 类型的 Enter Exit 方法的简化写法(请参见第14章和第23章)。 ies3fJ5kq+EHtxHDGyO6CuLvD8FuiFOBGi+it9mhYdRTJmlaGAn4IBJkPlMiRQ2I

点击中间区域
呼出菜单
上一章
目录
下一章
×