何谓直达?在C(和C++)中,忽略break并且按以下编写代码是完全合法的: nVar = 1switch (nVar){case 1:DoSomething();case 2:DoMore();} 在这个例子中,在执行了第一个case语句的代码后,将直接执行到其它case标签的代码,直到一个break语句退出switch语段为止。尽管有时这是一个强大的功能,但它更经常地产生难于发现的缺陷。 可如果你想执行其它case标签的代码,那怎么办? 有一种办法,它显示于清单6.3中。 清单 6.3 在swtich语句中使用 goto 标签 和 goto default 1: using System;2: 3: class SwitchApp4: {5: public static void Main()6: {7: Random objRandom = new Random();8: double dRndNumber = objRandom.NextDouble();9: int nRndNumber = (int)(dRndNumber * 10.0);10: 11: switch (nRndNumber)12: {13: case 1:14: //什么也不做15: break;16: case 2:17: goto case 3;18: case 3:19: Console.WriteLine("Handler for 2 and 3");20: break;21: case 4:22: goto default;23: // everything beyond a goto will be warned as24: // unreachable code25: default:26: Console.WriteLine("Random number {0}", nRndNumber);27: }28: }29: } 在这个例子中,通过Random类产生用于控制表达式的值(第7~9行)。switch语段包含两个对switch语句有效的跳转语句。 goto case 标签:跳转到所说明的标签 goto default: 跳转到 default 标签 有了这两个跳转语句,你可以创建同C一样的功能,但是,直达不再是自动的。你必须明确地请求它。不再使用直达功能的更深的含义为:你可任意排列标签,如把default标签放在其它所有标签的前面。为了说明它,我创建了一个例子,故意不结束循环: switch (nSomething){default:case 5:goto default;} 我已经保留了其中一个swich 语句功能的讨论直至结束——事实上你可以使用字符串作为常量表达式。这对于VB程序员,可能听起来不象是什么大的新闻,但来自C或C++的程序员将会喜欢这个新功能。 现在,一个 switch 语句可以如以下所示检查字符串常量了。 string strTest = "Chris";switch (strTest){case "Chris":Console.WriteLine("Hello Chris!");break;} 6.2 循环语句 当你想重复执行某些语句或语段时,依据当前不同的任务,C#提供4个不同的循环语句选择给你使用:。for 语句 。foreach 语句 。while 语句 。do 语句 6.2.1 for 语句 当你预先知道一个内含语句应要执行多少次时,for 语句特别有用。当条件为真时,常规语法允许重复地执行内含语句(和循环表达式): for (初始化;条件;循环) 内含语句 请注意,初始化、条件和循环都是可选的。如果忽略了条件,你就可以产生一个死循环,要用到跳转语句(break 或goto)才能退出。 for (;;){break; // 由于某些原因} 另外一个重点是,你可以同时加入多条由逗号隔开的语句到for循环的所有三个参数。例如,你可以初始化两个变量、拥有三个条件语句,并重复4个变量。作为C或C++程序员,你必须了解仅有的一个变化:条件语句必须为布尔表达式,就象 if 语句一样。 清单6.4 包含使用 for 语句的一个例子。它显示了如何计算一个阶乘,比使用递归函数调用还要快。 清单 6.4 在for 循环里计算一个阶乘 1: using System;2: 3: class Factorial4: {5: public static void Main(string[] args)6: {7: long nFactorial = 1;8: long nComputeTo = Int64.Parse(args[0]);9: 10: long nCurDig = 1;11: for (nCurDig=1;nCurDig <= nComputeTo; nCurDig++)12: nFactorial *= nCurDig;13: 14: Console.WriteLine("{0}! is {1}",nComputeTo, nFactorial);15: }16: } 尽管该例子过于拖沓,但它作为如何使用for 语句的一个开端。首先,我本应在初始化内部声明变量nCurDig:for (long nCurDig=1;nCurDig <= nComputeTo; nCurDig++) nFactorial *= nCurDig; 另一种忽略初始化的选择如下行,因为第10行在for 语句的外部初始化了变量。(记住C#需要初始化变量):for (;nCurDig <= nComputeTo; nCurDig++) nFactorial *= nCurDig; 另一种改变是把++操作符移到内含语句中:for ( ;nCurDig <= nComputeTo; ) nFactorial *= nCurDig++; 如果我也想摆脱条件语句,全部要做的是增加一条if 语句,用break 语句中止循环: for (;;){if (nCurDig > nComputeTo) break;nFactorial *= nCurDig++;} 除了用于退出for语句的break语句外,你还可以用continue 跳过当前循环,并继续下一次循环。 for (;nCurDig <= nComputeTo;){if (5 == nCurDig) continue; // 这行跳过了余下的代码nFactorial *= nCurDig++; } 6.2.2 foreach 语句 已经在Visual Basic 语言中存在了很久的一个功能是,通过使用For Each 语句收集枚举。C#通过foreach 语句,也有一个用来收集枚举的命令: foreach(表达式中的类型标识符) 内含语句 循环变量由类型和标识符声明,且表达式与收集相对应。循环变量代表循环正在为之运行的收集元素。 你应该知道不能赋一个新值给循环变量,也不能把它当作ref 或out 参数。这样引用在内含语句中被执行的代码。 你如何说出某些类支持foreach 语句? 简而言之,类必须支持具有 GetEnumerator()名字的方法,而且由其所返回的结构、类或者接口必须具有public 方法MoveNext() 和public 属性Current。如果你想知道更多,请阅读语言参考手册,它有很多关于这个话题的详细内容。 对于清单 6.5 中的例子,我恰好偶然选了一个类,实现了所有这些需要。我用它来列举被定义过的所有的环境变量。 清单 6.5 读所有的环境变量 1: using System;2: using System.Collections;3: 4: class EnvironmentDumpApp5: {6: public static void Main()7: {8: IDictionary envvars = Environment.GetEnvironmentVariables();9: Console.WriteLine("There are {0} environment variables declared", envvars.Keys.Count);10: foreach (String strKey in envvars.Keys)11: {12: Console.WriteLine("{0} = {1}",strKey, envvars[strKey].ToString());13: }14: }15: } 对GetEnvironmentVariables的调用返回一个IDictionary类型接口,它是由.NET框架中的许多类实现了的字典接口。通过 IDictionary 接口,可以访问两个收集:Keys 和 Values。在这个例子里,我在foreach语句中使用Keys,接着查找基于当前key值的值(第12行)。

评论