C# Switch 语句深度解析:从基础入门到高级应用指南 (附带实用示例)
欢迎来到 C# 编程世界!在编写程序时,我们经常需要根据不同的条件执行不同的代码块。最常见的工具是 if-else if-else
结构,它强大而灵活。然而,当需要根据一个变量的精确值在众多可能性中选择一个执行路径时,if-else if-else
可能会变得冗长且难以阅读。这时,C# 的 switch
语句就闪亮登场了。
switch
语句为我们提供了一种更清晰、更简洁的方式来处理基于单个表达式值的多重选择。它不仅提升了代码的可读性,在某些情况下,编译器还能对其进行优化,可能带来性能上的提升。
本文将带你深入了解 C# 中的 switch
语句,从最基础的语法和用法,到现代 C# 版本(如 C# 8.0 及更高版本)引入的强大新特性——switch
表达式和模式匹配。无论你是编程新手还是希望巩固基础知识的开发者,都能从中获益。
让我们开始这段 switch
语句的探索之旅吧!
第一部分:传统 Switch 语句的基础
1. 什么是 Switch 语句?
switch
语句是一种控制流语句,它允许程序根据一个表达式的值,在一系列可能的代码块中选择一个来执行。它非常适用于处理离散的、有限的值集合,例如整数、枚举成员、字符串或字符等。
想象一下这样的场景:你需要根据用户输入的数字(1 到 7)来打印对应是星期几。使用 if-else if
,代码可能会是这样:
“`csharp
int dayOfWeek = GetUserInput(); // 假设获取到用户输入的数字
if (dayOfWeek == 1)
{
Console.WriteLine(“星期一”);
}
else if (dayOfWeek == 2)
{
Console.WriteLine(“星期二”);
}
else if (dayOfWeek == 3)
{
Console.WriteLine(“星期三”);
}
// … 依此类推直到星期日
else
{
Console.WriteLine(“无效的输入”);
}
“`
这段代码功能上没问题,但是当可能性很多时,if-else if
链会变得很长,阅读和维护都比较麻烦。
使用 switch
语句,同样的功能可以这样实现:
“`csharp
int dayOfWeek = GetUserInput(); // 假设获取到用户输入的数字
switch (dayOfWeek)
{
case 1:
Console.WriteLine(“星期一”);
break;
case 2:
Console.WriteLine(“星期二”);
break;
case 3:
Console.WriteLine(“星期三”);
break;
case 4:
Console.WriteLine(“星期四”);
break;
case 5:
Console.WriteLine(“星期五”);
break;
case 6:
Console.WriteLine(“星期六”);
break;
case 7:
Console.WriteLine(“星期日”);
break;
default:
Console.WriteLine(“无效的输入”);
break;
}
“`
是不是感觉清晰了很多?这就是 switch
语句的核心价值所在。
2. Switch 语句的基本语法
传统的 switch
语句语法结构如下:
“`csharp
switch (expression)
{
case constant-value1:
// 当 expression 的值等于 constant-value1 时执行这里的代码
code_block1;
break; // 结束当前 case 并跳出 switch 语句
case constant-value2:
// 当 expression 的值等于 constant-value2 时执行这里的代码
code_block2;
break; // 结束当前 case 并跳出 switch 语句
// … 可以有任意数量的 case
case constant-valueN:
// 当 expression 的值等于 constant-valueN 时执行这里的代码
code_blockN;
break; // 结束当前 case 并跳出 switch 语句
default:
// 当 expression 的值不匹配任何 case 时执行这里的代码 (可选)
default_code_block;
break; // 结束 default 并跳出 switch 语句
}
“`
让我们分解一下这个结构:
switch (expression)
: 这是switch
语句的起始。expression
是一个表达式,它的值将被用来与各个case
后面的常量值进行比较。这个表达式的结果类型必须是switch
语句支持的类型(我们稍后会详细说明)。case constant-value:
: 这是一个case
标签,后面跟着一个常量值 (constant-value
)。constant-value
必须是编译时可确定的常量,并且其类型必须与expression
的类型兼容。当expression
的值等于某个case
后面的constant-value
时,该case
块下的代码就会被执行。code_block;
: 这是与case
标签关联的代码块。可以包含一条或多条语句。break;
: 这是switch
语句中至关重要的一部分。在传统的 C#switch
语句中,每个非空的case
块都必须显式地结束。通常使用break
语句来结束当前的case
的执行,并立即跳出整个switch
语句。如果不使用break
(或其他跳转语句如return
,throw
,goto case
,goto default
),编译器会报错。这是 C# 与 C/C++ 的一个重要区别,C/C++ 默认会“贯穿”(fall through)到下一个case
。C# 强制要求显式结束是为了避免意外的贯穿错误。- 特例: 如果一个
case
块是空的(没有任何语句,包括注释),那么它后面可以紧跟着另一个case
标签,实现多个值执行同一个代码块的效果。例如:
csharp
case 1:
case 2:
Console.WriteLine("输入了 1 或 2");
break;
这种空case
的语法是允许的,并且是实现多个值共享逻辑的标准方式。
- 特例: 如果一个
default:
: 这是可选的default
标签。如果expression
的值不匹配任何case
后面的constant-value
,那么default
块中的代码将被执行。default
标签可以出现在switch
块的任何位置,但通常习惯性地放在最后一个。如果default
块存在,它也会像普通case
一样需要显式结束(通常是break
)。
3. switch
语句支持的数据类型
在传统的 switch
语句中,expression
可以是以下类型之一:
- 整数类型:
sbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
- 字符类型:
char
- 布尔类型:
bool
(虽然可以使用,但不常见,通常if-else
更直观) - 字符串类型:
string
(C# 2.0 及更高版本支持) - 枚举类型:
enum
- 可空类型:上述类型的可空形式(例如
int?
,string?
,MyEnum?
)
需要注意的是,浮点类型(float
, double
, decimal
)不能直接用作 case
标签的常量值进行精确匹配,因为浮点数的相等性比较存在精度问题。虽然 switch
表达式本身的结果类型可以是浮点数,但你在 case
后面写 case 1.0:
这样的精确匹配是不被推荐或支持的。对于浮点数的范围或近似值比较,if-else if
结构通常是更好的选择。
4. break
的重要性与替代方案
正如前面提到的,在 C# 传统 switch
中,每个非空的 case
块都必须有一个显式的跳转语句来终止。最常见的是 break
。
除了 break
,你还可以使用:
return;
: 如果switch
语句在一个方法内部,return
会立即结束方法的执行,并跳出switch
。throw new Exception(...);
: 抛出异常也会终止当前的执行流程,自然也就跳出了switch
。goto case constant-value;
: 跳转到同一个switch
语句中的另一个case
标签。这通常用于处理具有共同逻辑的多个case
,但这种用法并不常见,并且可能使代码难以理解,应谨慎使用。goto default;
: 跳转到default
标签。
“`csharp
int statusCode = 404;
switch (statusCode)
{
case 200:
Console.WriteLine(“成功”);
// break; // 如果这里是 return,就不需要 break 了
return; // 假设在方法内部
case 404:
Console.WriteLine(“未找到”);
break; // 必须有 break
case 500:
Console.WriteLine(“服务器错误”);
throw new InvalidOperationException(“发生服务器错误”); // 抛出异常也会退出
case 400:
case 401: // 空 case,会贯穿到 403
case 403:
Console.WriteLine(“客户端错误或权限问题”);
break; // 必须有 break
default:
Console.WriteLine(“未知状态码”);
break; // default 也需要结束
}
// 如果 switch 中使用了 return/throw,这里的代码可能不会执行
Console.WriteLine(“Switch 语句执行完毕。”); // 如果 statusCode 是 404 或 400/401/403 或 default,会执行到这里
“`
在这个例子中,如果 statusCode
是 200,方法会直接返回,Switch 语句执行完毕。
这行代码就不会打印。如果是 500,会抛出异常,也不会打印后面的行。
5. default
标签的用法与位置
default
标签是可选的。它的作用是捕获所有未被任何 case
匹配到的值。提供 default
标签是一种良好的实践,它可以提高代码的健壮性,确保在面对意外输入时程序不会悄无声息地失败或行为异常。
default
标签的位置是灵活的,可以放在 switch
块内的任何地方。然而,将其放在所有 case
标签之后是最常见的做法,因为它符合逻辑流程——先尝试所有已知情况,最后处理其他所有情况。
“`csharp
char grade = ‘B’;
switch (grade)
{
case ‘A’:
Console.WriteLine(“优秀”);
break;
default: // default 放在中间也是允许的
Console.WriteLine(“良好、及格或其他”);
break;
case ‘B’:
Console.WriteLine(“良好”);
break;
case ‘C’:
Console.WriteLine(“及格”);
break;
case ‘D’:
case ‘F’:
Console.WriteLine(“不及格”);
break;
}
// 输出: 良好
“`
即使 default
放在中间,它的逻辑行为不变:只有当没有任何 case
匹配时,default
块才会被执行。因此,为了可读性,强烈建议将 default
放在最后。
6. Switch 语句 vs. If-Else If 链
什么时候选择 switch
,什么时候选择 if-else if
?
-
选择
switch
的场景:- 你需要根据一个单个变量的精确值来选择执行路径。
- 这些值是离散的常量。
- 有多个这样的离散值需要处理(通常3个或更多时,
switch
的优势更明显)。 - 当使用支持的类型(整数、字符、字符串、枚举等)时,
switch
通常比等价的if-else if
更简洁、更易读。
-
选择
if-else if
的场景:- 条件涉及范围或不等式(如
x > 10
,y <= 5
)。 - 条件涉及多个变量(如
x > 10 && y < 20
)。 - 条件是复杂的布尔表达式。
- 只需要判断少数几个(1或2个)离散值。
- 条件涉及范围或不等式(如
在性能方面,对于处理大量离散的整数或枚举值,C# 编译器有时可以将 switch
语句优化成一个跳转表(jump table)。这种情况下,无论匹配的值是第一个还是最后一个,查找和跳转的时间复杂度接近 O(1),而 if-else if
是 O(n)(平均需要检查一半的条件)。然而,对于字符串或其他类型,或者当 case
值分布稀疏时,编译器可能不会生成跳转表,而是使用其他的比较和跳转策略,性能差异可能不那么显著。总之,在大多数应用开发场景中,选择 switch
还是 if-else if
主要取决于代码的可读性和维护性,而非过早的性能优化。
“`csharp
// if-else if 适合范围判断
int score = 85;
if (score >= 90)
{
Console.WriteLine(“优秀”);
}
else if (score >= 80)
{
Console.WriteLine(“良好”);
}
else if (score >= 60)
{
Console.WriteLine(“及格”);
}
else
{
Console.WriteLine(“不及格”);
}
// switch 适合精确值判断
string command = “start”;
switch (command)
{
case “start”:
Console.WriteLine(“开始…”);
break;
case “stop”:
Console.WriteLine(“停止…”);
break;
case “pause”:
Console.WriteLine(“暂停…”);
break;
default:
Console.WriteLine(“未知命令”);
break;
}
“`
第二部分:现代 C# 的 Switch 新特性 (C# 7.0+)
随着 C# 语言的发展,switch
语句变得越来越强大和灵活,引入了模式匹配(Pattern Matching)的概念,并在 C# 8.0 中推出了全新的 switch
表达式。这些特性极大地扩展了 switch
的适用范围,使其能够处理更复杂的条件判断。
1. 模式匹配在 Switch 语句中的应用 (C# 7.0+)
C# 7.0 引入了模式匹配,并在后续版本中不断增强。这让 switch
语句不再仅仅局限于与常量值的精确匹配,而是可以匹配表达式的类型、形状、属性等。
在传统的 switch
语句中,模式匹配主要体现在以下几个方面:
-
类型模式 (
is
pattern): 检查表达式的类型是否与指定的类型兼容,如果匹配,可以同时将表达式转换为该类型并赋值给一个变量。“`csharp
object item = “Hello, World!”; // item 可以是任何类型switch (item)
{
case int i: // 如果 item 是 int 类型,将其值赋给变量 i
Console.WriteLine($”这是一个整数: {i}”);
break;
case string s: // 如果 item 是 string 类型,将其值赋给变量 s
Console.WriteLine($”这是一个字符串: {s.Length} 个字符”);
break;
case bool b: // 如果 item 是 bool 类型,将其值赋给变量 b
Console.WriteLine($”这是一个布尔值: {b}”);
break;
case null: // 也可以匹配 null
Console.WriteLine(“这是一个 null 值”);
break;
default:
Console.WriteLine($”未知类型: {item.GetType().Name}”);
break;
}
// 输出: 这是一个字符串: 13 个字符
``
case int i:
这里的就是一个类型模式,它检查
item是否是
int类型,如果是,就进入该
case块,并且可以在块中使用
i变量,它的类型是
int且值为
item` 转换后的值。 -
when
子句: 在case
标签后面添加一个when
子句,可以为该case
增加一个额外的布尔条件。只有当case
标签匹配成功 并且when
子句的条件为true
时,该case
块才会被执行。“`csharp
int number = 15;switch (number)
{
case int n when n > 10 && n <= 20: // 匹配大于10且小于等于20的整数
Console.WriteLine($”数字 {n} 在 10 到 20 之间”);
break;
case int n when n <= 10: // 匹配小于等于10的整数
Console.WriteLine($”数字 {n} 小于等于 10″);
break;
default: // 如果不是整数,或者不在上述范围内
Console.WriteLine(“数字超出范围或类型不符”);
break;
}
// 输出: 数字 15 在 10 到 20 之间
``
when` 子句非常灵活,可以用于各种模式后面,包括常量模式、类型模式等。
通过模式匹配和 when
子句,传统的 switch
语句能够处理更丰富的条件逻辑,而不仅仅是常量相等性检查。
2. Switch 表达式 (C# 8.0+)
C# 8.0 引入了 switch
表达式,这是一种与 switch
语句功能类似但语法更简洁、用于生成一个值的新结构。它通常用于简单的映射或转换场景,可以作为 if-else if
表达式或三元运算符的更具可读性的替代。
switch
表达式的语法如下:
csharp
result = expression switch
{
pattern1 => result1,
pattern2 => result2,
// ...
patternN => resultN,
_ => defaultResult // 弃元模式 (Discard Pattern) 作为默认情况 (可选,但通常需要确保穷尽所有可能性)
};
分解一下:
expression switch
: 这是switch
表达式的开始。expression
是要进行匹配的表达式。{ ... }
: 包含一系列的“arm”(臂)。pattern => result
: 每个 arm 包含一个模式 (pattern
) 和一个=>
符号,后面跟着一个结果表达式 (result
)。如果expression
匹配pattern
,则整个switch
表达式的值就是result
。pattern
: 可以是前面提到的各种模式,包括常量模式、类型模式、关系模式、属性模式等。result
: 匹配成功时返回的值或表达式。_
: 这是一个弃元模式 (Discard Pattern),它匹配任何值。在switch
表达式中,它通常用作类似传统switch
语句中default
的作用,用于处理所有未被其他模式匹配到的情况。如果switch
表达式不能覆盖所有可能的输入值(即不是“穷尽的”),并且没有包含弃元模式_
,那么在运行时可能会抛出异常。因此,通常建议包含一个_
模式作为 fallback。
重要区别:Switch 语句 vs. Switch 表达式
特性 | Switch 语句 (Statement) | Switch 表达式 (Expression) |
---|---|---|
用途 | 执行不同的代码块 (副作用) | 根据输入返回一个值 |
语法 | switch (...) { case ...: ... break; ... } |
... switch { ... => ..., ... } |
结束方式 | break , return , throw , goto case/default |
=> 后面的表达式求值完毕即返回该值,无需 break |
返回值 | 没有直接返回值 | 必须返回一个值 |
Default | 使用 default: 标签 |
使用弃元模式 _ |
穷尽性 | 不需要强制穷尽所有可能性 (default 可选) |
通常需要穷尽所有可能性 (否则可能运行时错误),常使用 _ |
Switch 表达式示例:
将数字映射到星期几的字符串:
“`csharp
int day = 3;
string dayName = day switch
{
1 => “星期一”,
2 => “星期二”,
3 => “星期三”,
4 => “星期四”,
5 => “星期五”,
6 => “星期六”,
7 => “星期日”,
_ => “无效的日期” // 弃元模式处理其他所有情况
};
Console.WriteLine(dayName); // 输出: 星期三
“`
这个例子比传统的 switch
语句写起来更紧凑,并且直接将结果赋值给 dayName
变量。
Switch 表达式也可以结合模式匹配和 when
子句:
“`csharp
object data = “hello”;
string dataTypeInfo = data switch
{
int i when i > 100 => $”大整数: {i}”, // 类型模式 + when
int i => $”小整数: {i}”, // 类型模式 (注意顺序,会先匹配上面的条件)
string s when s.Length > 5 => $”长字符串: {s}”, // 类型模式 + when
string s => $”短字符串: {s}”, // 类型模式
null => “空值”, // 常量模式
_ => $”未知类型: {data.GetType().Name}” // 弃元模式
};
Console.WriteLine(dataTypeInfo); // 输出: 短字符串: hello
``
switch` 表达式中,模式的顺序很重要。它们会按顺序进行评估,第一个匹配的模式对应的结果将被返回。因此,更具体的模式通常应该放在更通用的模式之前。
注意,在
3. 更高级的模式匹配 (C# 9.0+)
C# 9.0 及更高版本进一步增强了模式匹配的能力,使得 switch
表达式和 switch
语句(虽然 switch
表达式是模式匹配更常见的应用场景)能够处理更复杂的条件。
-
关系模式 (Relational Patterns): 允许使用关系运算符 (
<
,>
,<=
,>=
) 直接在case
或模式中比较表达式的值。“`csharp
int temperature = 25;string feeling = temperature switch
{
< 0 => “极寒”,
< 10 => “很冷”,
< 20 => “凉爽”,
< 30 => “温暖”,
< 40 => “炎热”,
_ => “极热或未知”
};
// 注意:关系模式也是按顺序评估的。比如 < 20 会在 < 10 之后评估,所以它只匹配 10-19 的范围。
// 这使得表达范围判断变得非常直观。Console.WriteLine(feeling); // 输出: 温暖
“`关系模式也可以与
when
子句结合使用,尽管通常关系模式本身已经足够表达范围。 -
逻辑模式 (Logical Patterns): 允许使用逻辑运算符
and
,or
,not
(或!
) 组合其他模式。“`csharp
int value = 5;string description = value switch
{
> 0 and < 10 => “正数且小于10”, // 组合关系模式
< 0 or > 100 => “负数或大于100”, // 组合关系模式
not 0 => “非零”, // 否定模式 (匹配所有非0的值)
_ => “零”
};Console.WriteLine(description); // 输出: 正数且小于10
“`
逻辑模式让你可以构建更精细的匹配条件。 -
属性模式 (Property Patterns): 允许匹配对象的特定属性的值。
假设有一个
Order
类:“`csharp
public class Order
{
public int OrderId { get; set; }
public decimal Total { get; set; }
public string Status { get; set; } // 例如: “Pending”, “Shipped”, “Delivered”
public Customer Customer { get; set; } // 假设 Customer 类有 Name 属性
}public class Customer
{
public string Name { get; set; }
// … 其他属性
}
“`使用属性模式进行匹配:
“`csharp
Order order = new Order { OrderId = 101, Total = 150.75m, Status = “Shipped”, Customer = new Customer { Name = “Alice” } };string orderStatus = order switch
{
{ Status: “Pending” } => “订单待处理”, // 匹配 Status 属性是 “Pending” 的 Order 对象
{ Status: “Shipped”, Total: > 100 } => “大额订单已发货”, // 组合属性模式和关系模式
{ Status: “Shipped” } => “订单已发货 (非大额)”,
{ Status: “Delivered”, Customer.Name: “Bob” } => “Bob 的订单已送达”, // 嵌套属性模式
{ Status: “Delivered” } => “订单已送达”,
null => “订单对象为空”, // 匹配 null
_ => “未知订单状态”
};Console.WriteLine(orderStatus); // 输出: 大额订单已发货
``
if (order != null && order.Status == “Shipped” && order.Total > 100)`。
属性模式非常强大,它允许你根据对象的内部状态进行复杂的条件判断,而无需写一长串的
这些现代模式匹配特性使得 switch
语句和 switch
表达式成为处理复杂分发逻辑的有力工具,提高了代码的表现力和可读性。
第三部分:实用建议与常见陷阱
1. 使用枚举 (Enum) 让 Switch 更安全、更清晰
在 switch
语句中使用枚举类型是一种非常推荐的做法。枚举提供了命名常量,提高了代码的可读性和可维护性。更重要的是,使用枚举可以减少因拼写错误等引起的潜在 bug,并且在面对新的枚举成员时,编译器或 IDE 可以提供警告(例如,如果 switch 语句没有覆盖枚举的所有成员)。
“`csharp
public enum TrafficLight
{
Red,
Yellow,
Green
}
TrafficLight currentLight = TrafficLight.Green;
switch (currentLight)
{
case TrafficLight.Red:
Console.WriteLine(“停车”);
break;
case TrafficLight.Yellow:
Console.WriteLine(“减速/等待”);
break;
case TrafficLight.Green:
Console.WriteLine(“通行”);
break;
// 通常建议包含 default 处理非预期的枚举值(虽然很少发生,除非外部数据源传入非法值)
default:
Console.WriteLine(“未知信号灯状态”);
break;
}
“`
2. 确保 Switch 表达式的穷尽性
使用 switch
表达式时,如果输入类型不是可空的引用类型或可空值类型,并且你没有包含一个匹配所有剩余可能值的模式(通常是弃元模式 _
),编译器可能会发出警告或错误,提示 switch
表达式不是穷尽的(non-exhaustive)。这意味着存在某些可能的输入值不会匹配任何模式。在运行时,如果遇到这样的值,switch
表达式将抛出 System.Runtime.CompilerServices.SwitchExpressionException
。
为了避免这种情况,请始终确保你的 switch
表达式能够处理所有可能的输入值。最简单的方法是包含一个 _
弃元模式作为最后一个 arm:
“`csharp
// 假设 StatusCode 是一个 int
int statusCode = 999;
string statusDescription = statusCode switch
{
200 => “OK”,
404 => “Not Found”,
500 => “Internal Server Error”,
// … 其他已知的状态码
_ => “未知状态码” // 确保所有其他 int 值都被处理
};
“`
如果输入类型是可空的(例如 int?
, string?
, MyEnum?
),你需要显式处理 null
情况,除非弃元模式 _
包含了对 null
的处理:
“`csharp
int? maybeNumber = null;
string result = maybeNumber switch
{
1 => “数字是 1”,
> 10 => “数字大于 10”,
null => “值是 null”, // 显式处理 null
_ => “其他数字” // 处理非 null 且不匹配前面模式的情况
};
Console.WriteLine(result); // 输出: 值是 null
``
_
这里的模式会匹配所有非 null 且不等于 1 且不大于 10 的
int` 值。
3. 避免在 Case 块中编写过于复杂的逻辑
虽然你可以在 case
或 default
块中编写任意复杂的代码,但如果代码块变得很长或包含嵌套结构,这会降低 switch
语句的可读性。良好的实践是将复杂的逻辑提取到单独的方法中,然后在 case
块中调用这些方法。
“`csharp
// 不推荐: case 块中逻辑复杂
switch (command)
{
case “process”:
// 大量处理逻辑,循环,条件判断等…
Console.WriteLine(“开始处理…”);
// … 很多行代码
break;
// …
}
// 推荐: 将逻辑提取到方法中
switch (command)
{
case “process”:
ProcessData(); // 调用单独的方法
break;
// …
}
void ProcessData()
{
// 大量处理逻辑…
Console.WriteLine(“正在处理数据…”);
// …
}
“`
4. 理解模式匹配的顺序
在 switch
表达式和带有模式匹配的 switch
语句中,模式是按顺序进行评估的。一旦找到第一个匹配的模式,对应的代码块或结果就会被执行/返回,然后退出 switch
。这意味着你应该将更具体或更窄的模式放在更通用或更宽泛的模式之前。
“`csharp
// 错误的顺序示例 (在 switch 表达式或语句中)
int x = 5;
string range = x switch
{
> 0 => “正数”, // 这个模式会匹配所有正数,包括大于100的
> 100 => “大于100的正数”, // 这一行永远不会被匹配到,因为所有大于100的数已经被上面的模式捕获了
_ => “非正数”
};
Console.WriteLine(range); // 输出: 正数 (即使 x = 150 也是输出 正数)
// 正确的顺序示例
int y = 150;
string correctRange = y switch
{
> 100 => “大于100的正数”, // 先检查最具体的范围
> 0 => “正数”, // 再检查更宽泛的范围
_ => “非正数”
};
Console.WriteLine(correctRange); // 输出: 大于100的正数
“`
理解这个顺序对于正确使用模式匹配至关重要。
5. 传统 Switch 语句中的贯穿 (Fall-through)
再次强调,C# 传统 switch
语句不允许非空的 case
块自动贯穿到下一个 case
。如果你需要让多个 case
执行相同的代码,有两种方法:
- 使用空的
case
标签:
csharp
case 1:
case 2:
Console.WriteLine("值为 1 或 2");
break; - 使用
goto case
或goto default
(不推荐用于初学者,可能导致代码难以理解):
csharp
int num = 5;
switch (num)
{
case 5:
Console.WriteLine("处理 5 的特有逻辑");
goto case 10; // 跳转到 case 10
case 10:
Console.WriteLine("处理 5 和 10 的共享逻辑");
break;
default:
Console.WriteLine("其他");
break;
}
// 输出:
// 处理 5 的特有逻辑
// 处理 5 和 10 的共享逻辑
除非必要且非常清晰,否则优先使用空的 case
标签来实现多个值共享逻辑。
结论
C# 的 switch
语句是一个强大而灵活的控制流结构,尤其适用于基于单个表达式离散值的选择场景。从传统的基于常量值的匹配,到现代 C# 通过模式匹配和 switch
表达式带来的类型检查、属性检查、范围判断和逻辑组合能力,switch
的功能得到了极大的扩展。
掌握 switch
语句及其现代特性,能够帮助你编写出更清晰、更简洁、更富有表现力的 C# 代码。在处理多分支逻辑时,请考虑 switch
是否是比 if-else if
更合适的工具。熟练运用 switch
表达式和各种模式,将是你在现代 C# 开发中迈出的重要一步。
实践是学习的最佳途径。尝试在你自己的代码中使用 switch
语句和 switch
表达式,特别是结合模式匹配,去解决实际问题,你将更快地掌握这些强大的工具。
希望这篇详细的指南对你理解和使用 C# switch
语句有所帮助!祝你编程愉快!