首页 > 编程笔记 > C#笔记 阅读:61

C# switch语句的用法(非常详细)

C# 中的 switch 语句能够根据变量可能的取值来转移程序的执行。

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 子句结束时必须使用某种跳转指令显式指定下一个执行点(除非你的代码本身就是一个无限循环),这些跳转指令有:
当多个值需要执行相同的代码时,可以按照顺序列出共同的 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",
    ...
};

相关文章