C# switch语句的用法(非常详细)
C# 中的 switch 语句能够根据变量可能的取值来转移程序的执行。
switch 语句可以拥有比嵌套 if 语句更加简洁的代码,因为 switch 语句仅仅需要一次表达式计算:
每一个 case 子句结束时必须使用某种跳转指令显式指定下一个执行点(除非你的代码本身就是一个无限循环),这些跳转指令有:
当多个值需要执行相同的代码时,可以按照顺序列出共同的 case 条件:
C# 支持按类型 switch(从 C#7 开始):
when 关键字可用于对 case 进行预测,例如:
如果希望按照类型进行 switch,但对其值却并不关心,这种情况下可以使用“丢弃”变量(_):
除此以外,还可以混合使用常量选择和模式选择,甚至可以选择 null 值:
以下示例展示了该功能的使用方法,其中,假定变量 cardNumber 是 int 类型:
switch 语句可以拥有比嵌套 if 语句更加简洁的代码,因为 switch 语句仅仅需要一次表达式计算:
void ShowCard(int cardNumber) { switch (cardNumber) { case 13: Console.WriteLine("国王"); break; case 12: Console.WriteLine("皇后"); break; case 11: Console.WriteLine("杰克"); break; case -1: // 小丑角是 -1 goto case 12; // 在这个游戏中丑角算作皇后 default: // 执行任何其他 cardNumber Console.WriteLine(cardNumber); break; } }这个例子演示了最一般的情形,即针对常量的 switch。当指定常量时,只能指定内置的整数类型、bool、char、enum 类型以及 string 类型。
每一个 case 子句结束时必须使用某种跳转指令显式指定下一个执行点(除非你的代码本身就是一个无限循环),这些跳转指令有:
- break:跳转到 switch 语句的最后;
- goto case x:跳转到另外一个 case 子句;
- goto default:跳转到 default 子句;
- 其他的跳转语句,例如,return、throw、continue 或者 goto label。
当多个值需要执行相同的代码时,可以按照顺序列出共同的 case 条件:
switch (cardNumber) { case 13: case 12: case 11: Console.WriteLine("Face card"); break; default: Console.WriteLine("Plain card"); break; }switch 语句的这种特性可以写出比多个 if-else 更加简洁的代码。
C#按类型switch
按照类型进行 switch 是带有模式的 switch 语句的一种特殊的使用情况,最近几版 C# 语言引入了多种模式。C# 支持按类型 switch(从 C#7 开始):
TellMeTheType(12); TellMeTheType("hello"); TellMeTheType(true); void TellMeTheType(object x) // object 允许任何类型 { switch (x) { case int i: Console.WriteLine("It's an int!"); Console.WriteLine($"The square of {i} is {i * i}"); break; case string s: Console.WriteLine("It's a string"); Console.WriteLine($"The length of {s} is {s.Length}"); break; default: Console.WriteLine("I don't know what x is"); break; } }每一个 case 子句都指定了一种需要匹配的类型和一个变量(模式变量),如果类型匹配成功就对变量赋值。和常量不同,子句对可用的类型并没有进行任何限制。
when 关键字可用于对 case 进行预测,例如:
switch (x) { case bool b when b == true: // 仅当 b 为 true 时触发 Console.WriteLine("True!"); break; case bool b: Console.WriteLine("False!"); break; }case 子句的顺序会影响类型的选择(这和选择常量的情况有些不同)。如果交换 case 的顺序,则上述示例可以得到完全不同的结果(事实上,上述程序甚至无法编译,因为编译器发现第二个 case 子句是永远不会执行的)。但 default 子句是一个例外,不论它出现在什么地方都会在最后才执行。
如果希望按照类型进行 switch,但对其值却并不关心,这种情况下可以使用“丢弃”变量(_):
case DateTime _: Console.WriteLine("It's a DateTime");堆叠多个 case 子句也是没有问题的。在下面的例子中,Console.WriteLine 会在任何浮点类型的值大于 1000 时执行:
switch (x) { case float f when f > 1000: case double d when d > 1000: case decimal m when m > 1000: Console.WriteLine("We can refer to x here but not f or d or m"); break; }在上述例子中,编译器仅允许在 when 子句中使用模式变量 f、d 和 m。当调用 Console.WriteLine 时,我们并不清楚到底三个模式变量中的哪一个会被赋值,因而编译器会将它们放在作用域之外。
除此以外,还可以混合使用常量选择和模式选择,甚至可以选择 null 值:
case null: Console.WriteLine("Nothing here"); break;
C# switch表达式
从 C#8 开始,我们可以在表达式中使用 switch。以下示例展示了该功能的使用方法,其中,假定变量 cardNumber 是 int 类型:
string cardName = cardNumber switch { 13 => "King", 12 => "Queen", 11 => "Jack", _ => "Pip card" // 相当于 'default' };注意,switch 是在变量名称之后出现的,且其中的 case 子句相应地变为了以逗号结尾的表达式(而不再是语句)。switch 表达式相比 switch 语句更加紧凑,且可以用于 LINQ 查询。
switch 表达式也支持多变量的选择(元组模式):如果在 switch 表达式中忽略默认表达式(_)同时其他条件匹配失败,则会抛出一个异常。
int cardNumber = 12; string suite = "spades"; string cardName = (cardNumber, suite) switch { (13, "spades") => "King of spades", (13, "clubs") => "King of clubs", ... };