C# 编程/控制
条件、迭代、跳转和异常处理语句控制程序的执行流程。
条件语句可以使用 if
、switch
等关键字来决定某些事情。
迭代语句可以使用 do
、while
、for
、foreach
和 in
等关键字来创建循环。
跳转语句可以使用 break
、continue
、return
和 yield
等关键字来转移程序控制。
条件语句根据条件决定是否执行代码。在 C# 中,if
语句和 switch
语句是两种类型的条件语句。
与大多数 C# 一样,if
语句的语法与 C、C++ 和 Java 中相同。因此,它以以下形式编写
if (condition)
{
// Do something
}
else
{
// Do something else
}
if
语句评估其条件表达式以确定是否执行if-body。可选地,else
子句可以紧跟在if body 之后,提供当条件为false 时要执行的代码。使else-body 成为另一个if
语句创建了常见的if
、else if
、else if
、else if
、else
语句的级联
using System;
public class IfStatementSample
{
public void IfMyNumberIs()
{
int myNumber = 5;
if ( myNumber == 4 )
Console.WriteLine("This will not be shown because myNumber is not 4.");
else if( myNumber < 0 )
{
Console.WriteLine("This will not be shown because myNumber is not negative.");
}
else if( myNumber % 2 == 0 )
Console.WriteLine("This will not be shown because myNumber is not even.");
else
{
Console.WriteLine("myNumber does not match the coded conditions, so this sentence will be shown!");
}
}
}
switch
语句类似于 C、C++ 和 Java 中的语句。
与 C 不同,每个case
语句都必须以跳转语句结束(可以是 break
或 goto
或 return
)。换句话说,C# 不支持从一个case
语句到下一个case
语句的“穿透”(从而消除了 C 程序中常见的不预期行为来源)。但是允许“堆叠”案例,如下面的示例所示。如果使用 goto
,它可以引用 case 标签或默认 case(例如 goto case 0
或 goto default
)。
default
标签是可选的。如果没有定义默认情况,那么默认行为是不执行任何操作。
一个简单的例子
switch (nCPU)
{
case 0:
Console.WriteLine("You don't have a CPU! :-)");
break;
case 1:
Console.WriteLine("Single processor computer");
break;
case 2:
Console.WriteLine("Dual processor computer");
break;
// Stacked cases
case 3:
// falls through
case 4:
// falls through
case 5:
// falls through
case 6:
// falls through
case 7:
// falls through
case 8:
Console.WriteLine("A multi processor computer");
break;
default:
Console.WriteLine("A seriously parallel computer");
break;
}
与 C switch 语句相比,一个很好的改进是 switch 变量可以是字符串。例如
switch (aircraftIdent)
{
case "C-FESO":
Console.WriteLine("Rans S6S Coyote");
break;
case "C-GJIS":
Console.WriteLine("Rans S12XL Airaile");
break;
default:
Console.WriteLine("Unknown aircraft");
break;
}
迭代语句创建一个循环代码,以便执行可变次数。在 C# 中,for
循环、do
循环、while
循环和 foreach
循环是迭代语句。
do...while
循环也与其他从 C 派生的语言具有相同的语法。它以以下形式编写
- do...while-loop ::= "do" body "while" "(" condition ")"
- condition ::= boolean-expression
- body ::= statement-or-statement-block
do...while
循环总是运行其body 一次。在第一次运行之后,它会评估其condition 以确定是否再次运行其body。如果condition 为true,则执行body。如果condition 在body 运行后再次评估为true,则再次执行body。当condition 评估为false 时,do...while
循环结束。
using System;
public class DoWhileLoopSample
{
public void PrintValuesFromZeroToTen()
{
int number = 0;
do
{
Console.WriteLine(number++.ToString());
} while(number <= 10);
}
}
上面的代码将从 0 到 10 的整数写入控制台。
for
循环也与其他从 C 派生的语言具有相同的语法。它以以下形式编写
- for-loop ::= "for" "(" initialization ";" condition ";" iteration ")" body
- initialization ::= variable-declaration | list-of-statements
- condition ::= boolean-expression
- iteration ::= list-of-statements
- body ::= statement-or-statement-block
initialization 变量声明或语句在第一次遍历for
循环时执行,通常用于声明和初始化索引变量。在每次遍历body 之前评估condition 表达式以确定是否执行 body。它通常用于测试索引变量是否超过某个限制。如果condition 评估为true,则执行body。在每次遍历body 之后执行iteration 语句,通常用于增加或减少索引变量。
public class ForLoopSample
{
public void ForFirst100NaturalNumbers()
{
for (int i = 0; i < 100; i++)
{
System.Console.WriteLine(i.ToString());
}
}
}
上面的代码将从 0 到 99 的整数写入控制台。
在 C# 中,foreach
语句类似于 for
语句,它们都允许代码迭代集合中的项目,但 foreach
语句缺少迭代索引,因此它即使对于完全没有索引的集合也能正常工作。它的写法如下:
- foreach-loop ::= "foreach" "(" variable-declaration "in" enumerable-expression ")" body
- body ::= statement-or-statement-block
enumerable-expression 是一个实现了 '''IEnumerable'''
的类型的表达式,因此它可以是数组或集合。variable-declaration 声明一个变量,该变量将在每次遍历body时被设置为enumerable-expression 的后续元素。当enumerable-expression 中没有更多元素可以分配给variable-declaration 的变量时,foreach
循环退出。
public class ForEachSample
{
public void DoSomethingForEachItem()
{
string[] itemsToWrite = {"Alpha", "Bravo", "Charlie"};
foreach (string item in itemsToWrite)
System.Console.WriteLine(item);
}
}
在上面的代码中,foreach
语句迭代字符串数组的元素,将 "Alpha"、"Bravo" 和 "Charlie" 写入控制台。
while
循环的语法与其他源自 C 的语言相同。它的写法如下:
- while-loop ::= "while" "(" condition ")" body
- condition ::= boolean-expression
- body ::= statement-or-statement-block
while
循环评估其condition 以确定是否运行其body。如果condition 为true,则body 执行。如果condition 随后再次评估为true,则body 再次执行。当condition 评估为false 时,while
循环结束。
using System;
public class WhileLoopSample
{
public void RunForAWhile()
{
TimeSpan durationToRun = new TimeSpan(0, 0, 30);
DateTime start = DateTime.Now;
while (DateTime.Now - start < durationToRun)
{
Console.WriteLine("not finished yet");
}
Console.WriteLine("finished");
}
}
跳转语句可用于使用诸如 break
、continue
、return
、yield
和 throw
等关键字来转移程序控制。
break 语句用于退出 switch 语句中的 case,也用于退出 for、foreach、while、do..while 循环,这将把控制权转移到循环结束后的下一条语句。
using System;
namespace JumpSample
{
public class Entry
{
static void Main(string[] args)
{
int i;
for (i = 0; i < 10; i++) // see the comparison, i < 10
{
if (i >= 3)
{
break;
// Not run over the code, and get out of loop.
// Note: The rest of code will not be executed,
// & it leaves the loop instantly
}
}
// Here check the value of i, it will be 3, not 10.
Console.WriteLine("The value of OneExternCounter: {0}", i);
}
}
}
continue
关键字在循环结束之前转移程序控制。然后检查循环的条件,如果满足条件,则循环执行另一次迭代。
using System;
namespace JumpSample
{
public class Entry
{
static void Main(string[] args)
{
int OneExternCounter = 0;
for (int i = 0; i < 10; i++)
{
if (i >= 5)
{
continue; // Not run over the code, and return to the beginning
// of the scope as if it had completed the loop
}
OneExternCounter += 1;
}
// Here check the value of OneExternCounter, it will be 5, not 10.
Console.WriteLine("The value of OneExternCounter: {0}", OneExternCounter);
}
}
}
return
关键字标识函数或方法的返回值(如果有),并将控制权转移到函数的末尾。
namespace JumpSample
{
public class Entry
{
static int Fun()
{
int a = 3;
return a; // the code terminates here from this function
a = 9; // here is a block that will not be executed
}
static void Main(string[] args)
{
int OnNumber = Fun();
// the value of OnNumber is 3, not 9...
}
}
}
yield
关键字用于定义一个迭代器块,该块为枚举器生成值。它通常用在 IEnumerable
接口的方法实现中,作为创建迭代器的一种简单方法。它的写法如下:
- yield ::= "yield" "return" expression
- yield ::= "yield" "break"
以下示例演示了在 MyCounter
方法中使用 yield 关键字。此方法定义一个迭代器块,并将返回一个枚举器对象,该对象生成从零到 stop
的计数器值,每次生成的值都增加 step
。
using System;
using System.Collections;
public class YieldSample
{
public static IEnumerable MyCounter(int stop, int step)
{
int i;
for (i = 0; i < stop; i += step)
{
yield return i;
}
}
static void Main()
{
foreach (int j in MyCounter(10, 2))
{
Console.WriteLine("{0} ", j);
}
// Will display 0 2 4 6 8
}
}
throw
关键字抛出异常。如果它位于 try 块内,它将把控制权转移到与异常匹配的 catch 块 - 否则,它将检查任何调用函数是否包含在匹配的 catch 块内,并将执行转移到那里。如果没有任何函数包含 catch 块,则程序可能会由于未处理的异常而终止。
namespace ExceptionSample
{
public class Warrior
{
private string Name { get; set; }
public Warrior(string name)
{
if (name == "Piccolo")
{
throw new Exception("Piccolo can't battle!");
}
}
}
public class Entry
{
static void Main(string[] args)
{
try
{
Warrior a = new Warrior("Goku");
Warrior b = new Warrior("Vegeta");
Warrior c = new Warrior("Piccolo"); // exception here!
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
异常和 throw 语句在异常章节中进行了更详细的描述。