C#程序的执行都是一行接一行、自上而下地进行,不遗漏任何代码。为了让程序能按照开发者所设计的流程进行执行,必然需要进行条件判断、循环和跳转等过程,这就需要实现流程控制。C#中的流程控制包含了条件语句、循环语句、跳转语句和异常处理四个方面。
一、跳转语句
break语句:终止并跳出循环体。
continue语句:终止当前循环,重新开始一个新的循环。
goto语句:跳转到指定位置。
C#允许给代码行加上标签,这样就可以使用goto语句直接跳转到这些代码行上。goto语句的用法如下:
goto<labelName>;
标签用下述方式定义:
<labelName>:
goto语句有两个限制,不能跳转到像for循环这样的代码块中,也不能跳出类的范围,不能退出try…catch语句后面的finally块。
这里讲解goto语句只为了解其语法,当遇到时能知道代码的意思,本人不建议使用。
return语句:跳出循环及其包含的函数。
throw语句:抛出一个异常。
二、条件语句
条件语句可以根据条件是否满足或者根据表达式的值控制代码的执行分支。C#有两种控制控制代码分支的结构,分别是if语句和switch语句。
if语句
注意:if语句的条件可以是布尔变量,也可以是表达式,但如果是表达式,则表达式得到的结果必须是布尔值。
1、单选择if语句,即条件成立执行,语法如下:
if(条件)
{
do;
}
2、ifelse语句,即条件成立执行A否则执行B,语法如下:
if(条件)
{
do A;
}
else
{
do B;
}
延伸:三元运算符?:也相当于一个ifelse语句,语法如下:<表达式> ? <resultIfTrue> : <resultIfFalse> 其中计算表达式可得到一个布尔值,
运算符的结果根据这个值来确定是<resultIfTrue>,还是<resultIfFalse>。例:
int a = 8; string b = (a < 10) ? "小于10" : "大于10";
3、多选择if语句,即对多个条件进行判断,成立的执行,语法如下:
if(条件1)
{
do A;
}
else if(条件2)
{
do B;
}
else if(条件3)
{
do C;
}
else
{
do D;
}
其中else if语句的个数不受限制,但是如果else if语句的个数较多,则应该考虑另一种分支结构:switch语句。
注意:多选择if语句自上而下,只要有一个条件成立就不会去判断其它任何条件。
switch语句
switch…case语句适合于从一组互斥的分支中选择一个执行分支。其形式是switch参数的后面跟一组case子句。如果switch参数中表达式的值等于某个case子句旁边的某个值,就执行该case子句中的代码。此时不需要使用花括号把语句组合到块中,只需使用break语句标记每段case代码的结尾即可。也可以在switch语句中包含一条default子句,如果表达式不等于任何case子句的值,就执行default子句的代码。其语法如下:
switch(表达式)
{
case 1:
Console.WriteLine("1");
break;
case 2:
Console.WriteLine("2");
break;
case 3:
Console.WriteLine("3");
break;
default:
Console.WriteLine("4");
break;
}
注意:switch语句每个case语句后面的值必须与表达式所得到的值的类型相同,而且必须是常量,不能是变量;switch语句中所有case语句后面的值必须是互斥的,也就是说case后面的值不能存在两个相同的值,因为所有case语句后面的值必须是互斥的,所以case语句的排放顺序无关紧要,甚至可以把default语句放在最前面!但是为养成良好的编程习惯和代码有清晰的逻辑,我不建议这样写;switch语句中default语句只能存在一个,不能存在多个;通常情况下,每个case后面都必须有一个break语句,break语句作用是中断switch语句的执行,但C#中也可以使用其它中断语句来中断switch语句的执,如return语句、goto语句。使用break语句和return语句来中断是有区别的,break语句仅仅中断switch语句的执行,如果switch语句后面还有其它代码是可以继续执行的,但是return语句中断则会中断switch语句所在的方法,也就是说switch语句后面的代码将不会执行,switch语句所在的方法将直接返回。使用goto语句可以从一个case跳到另一个case中执行,如下面这段代码:
int a = 1; switch (a) { case 1: Console.WriteLine("1"); goto case 2; case 2: Console.WriteLine("2"); break; case 3: Console.WriteLine("3"); break; default: Console.WriteLine("4"); break; }
程序说明:程序执行完 case 1后会直接执行case 2。但是我们不建议这样做,这会导致很难察觉的逻辑错误。
通常情况下switch语句中一个case语句处理完成后,不能自由的进入下一个case语句,但是这个规则有一个例外。如果把多个case语句放在一起,其后面加一个代码块,实际上是一次检查多个条件,如果满足这些条件中的任何一个,就会执行代码,例如:
int a = 2; switch (a) { case 1: case 2: case 3: Console.WriteLine("1或者2或者3"); break; default: Console.WriteLine("4"); break; }
三、循环语句
循环就是重复执行语句,循环结构可以实现一个程序模块的重复执行,它对我们简化程序、更好的组织算法有着重要的意义。
1、do循环
do循环的结构如下:
do
{
语句或语句块;
}while (表达式);
do循环先执行语句或语句块,然后再判断表达式的值,如果表达式的值为true,则继续执行循环,直到表达式的值为false。注意:do循环刚执行的时候不管表达式的值为true或者是false它都要先执行一次语句或语句块,然后再来判断表达式的值。也就是说如果一开始表达式的值为false,它也会执行一次循环。do循环无论布尔表达式的值是true还是false,语句或语句块至少会执行一次。另外while语句后面必须使用分号(;)。
2、while循环
while循环的结构如下:
while(表达式)
{
语句或语句块;
}
while循环则是先判断表达式的值,然后再执行语句或语句块,直到表达式的值为false。如果循环刚开始表达式的值就为false,那么语句或语句块就不会被执行。
3、for循环
for循环的结构如下:
for(<初始化表达式>;<条件表达式>;<迭代表达式>)
{
语句或语句块;
}
初始化表达式:可以在该位置定义一个变量并为其赋一个起始值,也可以使用for循环前面定义的变量,但是使用for循环前面定义的变量必须在该位置为其重新赋一个起始值。注意:在该位置定义一个变量并为其赋一个起始值,这种用法定义的变量的作用域仅在for循环语句中,也就是说for循环语句后面的代码就不能使用该变量;但是用for循环前面定义的变量这种用法定义的变量for循环语句后面的代码就也能使用该变量。
条件表达式:它是循环继续或者终止的条件。
迭代表达式:执行完语句或语句块后就执行迭代表达式,然后再执行条件表达式判断循环是否继续。
for循环示例:
//将1到10打印到屏幕上 for (int a =1 ; a <= 10; a++) { Console.WriteLine(a); } Console.ReadKey();
4、foreach循环
foreach语句用于枚举一个集合的元素,并对该集合中的每一个元素执行一次嵌入语句。foreach循环的结构如下:
foreach(<类型> <迭代变量名> in <集合>)
{
语句或语句块;
}
注意:迭代变量的类型必须与集合的类型相同。集合内元素的个数决定循环内程序段重复执行的次数,每次进入循环,会依次将集合元素内容指定给变量,当所有元素都读完后,就会跳出foreach循环。foreach循环对集合内元素进行只读访问,不能改变任何元素的值。foreach循环在循环的过程中不能对集合进行添加元素或者删除元素的操作。示例:
List<string> strList = new List<string>(); for (int a =1 ; a <= 10; a++) { strList.Add(a.ToString()); } foreach (string str in strList) { Console.WriteLine(str); strList.Remove(str); } Console.ReadKey();
以上程序中的foreach语句在输出集合strList中的第一元素并将其移除集合后进行下一次循环的时候会产生异常。
5、无限循环
在代码编写错误或者故意进行设计时,可以定义永不终止的循环,即所谓的无限循环。示例:
while(true)
{
语句或语句块;
}
无限循环语句也是有用的,而且可以使用break语句或者手工使用Windows任务管理器退出无限循环。
四、异常处理
C#中的异常处理也算一种流程控制,try…catch…finally语句用于异常的捕获和处理,具体语法如下:
try
{
语句或语句块;
}
catch(<execptionType> e)
{
语句或语句块;
}
finally
{
语句或语句块;
}
try:包含抛出异常的代码。
catch:包含抛出异常时要执行的代码。catch块可以使用<execptionType>设置为只响应特定的异常类型,以便提供多个catch块。
finally:包含始终会执行的代码,如果没有产生异常,则在try块之后执行,如果处理了异常,就在catch块后执行。
try…catch…finally语句的执行顺序依次是:
1、try块在发生异常的地方中断程序的执行。
2、如果有catch块,就检查该块是否匹配已抛出的异常类型。如果没有catch块,就执行finally块(如果没有catch块,就一定要有finally块)。
3、如果有catch块,但它与已发生的异常类型不匹配,就检查是否有其他catch块。
4、如果有catch块匹配已发生的异常类型,就执行它包含的代码,再执行finally块(如果有)。
5、如果catch块都不匹配已发生的异常类型,就执行finally块(如果有)。
从try…catch…finally语句的执行顺序可以看出try…catch…finally语句有多种组合模式,这里就不详细讲解作者:贤俊