Skip to content

C# - Switch语句

在 C# 中,switch 构造提供了一种简洁的方式,根据变量或表达式的值来控制程序流程。它允许你通过将一个值与一系列可能的 case 进行比较,来执行不同的代码块。现代 C# 提供了两种形式:传统的 switch 语句 和更简洁的 switch 表达式。

switch 语句是一种控制流语句,它执行与匹配的 case 标签关联的代码。

switch (expression)
{
case constant_value1:
// 要执行的代码
break; // 退出 switch
case constant_value2:
// 要执行的代码
break;
// 你可以有任意数量的 case 语句
default: // 可选
// 如果没有其他 case 匹配,则执行的代码
break;
}
  • 表达式类型:switch 语句中的表达式可以是整型(int、char、byte…)、string、enum,或者,在现代 C# 中,由于模式匹配的支持,可以是任何类型。
  • break 是必需的:每个非空的 case 代码块必须以一个跳转语句结束,最常见的是 break。这可以防止意外的“穿透”(fall-through),在 C++ 等其他语言中,“穿透”是常见的 bug 来源。
  • 空 case 的穿透:你可以堆叠 case 标签,为多个值执行相同的代码。编译器只允许从空的 case 标签进行穿透。
  • default 情况:可选的 default 情况会在没有其他 case 表达式与 switch 表达式匹配时执行。它可以放置在 switch 块中的任何位置,但通常放在最后。
  1. switch 表达式被求值一次。
  2. 程序控制跳转到其常量值与表达式结果匹配的 case 标签。
  3. 该 case 块内的代码会一直执行,直到遇到 break 语句。
  4. 如果遇到 break,控制流将跳到 switch 块之后的第一个语句。
  5. 如果没有 case 标签匹配,控制流将跳转到 default 块(如果存在)。
using System;
char grade = 'B';
string feedback;
switch (grade)
{
case 'A':
feedback = "Excellent!";
break;
case 'B':
case 'C':
feedback = "Well done.";
break;
case 'D':
feedback = "You passed.";
break;
case 'F':
feedback = "Better try again.";
break;
default:
feedback = "Invalid grade.";
break;
}
Console.WriteLine($"Feedback for grade {grade}: {feedback}");
// Output: Feedback for grade B: Well done.

现代 C#:switch 表达式(C# 8.0 及更高版本)

Section titled “现代 C#:switch 表达式(C# 8.0 及更高版本)”

switch 表达式提供了一种更简洁、更具函数式风格的语法。它不是一个控制流程的语句,而是一个返回值的表达式。

var result = variableToSwitchOn switch
{
pattern1 => expression1,
pattern2 => expression2,
_ => defaultExpression // _ 是弃元模式,等同于 default
};

之前的示例可以更优雅地重写:

using System;
char grade = 'B';
string feedback = grade switch
{
'A' => "Excellent!",
'B' or 'C' => "Well done.", // 用于匹配多个值的 'or' 模式
'D' => "You passed.",
'F' => "Better try again.",
_ => "Invalid grade."
};
Console.WriteLine($"Feedback for grade {grade}: {feedback}");
// Output: Feedback for grade B: Well done.

现代 switch 语句和表达式支持模式匹配,它允许你根据对象的属性、类型或其他特征进行切换,而不仅仅是常量值。

想象一下根据目的地和订单总额计算运费。使用带有属性模式的 switch 表达式非常适合此场景。

public record Order(decimal Total, string DestinationCountry);
public decimal CalculateShipping(Order order)
{
return order switch
{
// 属性模式:检查订单对象的属性
{ DestinationCountry: "USA" } => 5.00m,
// 带有 when 子句的属性模式,用于附加逻辑
{ DestinationCountry: "EU", Total: > 100.0m } => 0.00m, // 欧盟地区订单金额超过 100 免费送货
{ DestinationCountry: "EU" } => 10.00m,
// 弃元模式:捕获所有其他情况
_ => 20.00m // 国际运费
};
}
// 用法:
var myOrder = new Order(150.0m, "EU");
Console.WriteLine($"Shipping cost: {CalculateShipping(myOrder):C}");
// Output: Shipping cost: $0.00
  • 对于简单的布尔条件或少量检查,使用 if-else if。
  • 当你需要根据一个值执行不同的语句块(多行代码)且不需要直接返回结果时,使用 switch 语句。
  • 当你需要根据一组条件生成单个值时,使用 switch 表达式。它更简洁且不易出错。