C#的switch语句有哪些新特性?如何模式匹配?

小老鼠
发布: 2025-09-09 08:44:01
原创
488人浏览过
<blockquote>C#的switch语句通过引入模式匹配和switch表达式,实现了从简单值比较到复杂数据形状匹配的跃迁,支持类型、属性、关系等多种模式,结合执行顺序与穷尽性检查,显著提升代码可读性与安全性。</blockquote> <p><img src="https://img.php.cn/upload/article/001/221/864/175737864127378.jpg" alt="c#的switch语句有哪些新特性?如何模式匹配?"></p> <p>C#的<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句在近年来的版本迭代中,已经从一个相对简单的值比较<a style="color:#f60; text-decoration:underline;" title="工具" href="https://www.php.cn/zt/16887.html" target="_blank">工具</a>,演变为一个功能强大的模式匹配表达式,极大地提升了代码的可读性和表达力。它不再仅仅是判断一个变量的离散值,而是能够根据数据的形状、类型、属性甚至关系进行复杂的匹配,让原本冗长的<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">if-else if</pre>
登录后复制
</div>链变得简洁优雅。</p> <p>C#的<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句在最近几个版本中迎来了翻天覆地的变化,最核心的莫过于引入了<strong>模式匹配(Pattern Matching)</strong>以及<strong><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式(Switch Expressions)</strong>。这些新特性让代码处理复杂逻辑时,变得更加清晰和富有表现力。</p> <p><strong>解决方案</strong></p> <p>我们来具体看看这些新特性是如何工作的,以及如何利用它们进行模式匹配:</p> <p><strong>1. <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式(C# 8.0)</strong></p> <p>这是最直观的变化。传统的<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句主要用于执行副作用(如打印消息),而<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式则用于计算并返回一个值。它的语法更紧凑,使用<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">=></pre>
登录后复制
</div>来连接模式和结果,并且通常不需要<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">break</pre>
登录后复制
</div>关键字,因为每个分支都必须返回一个值。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>// 传统switch语句 string GetDayTypeTraditional(DayOfWeek day) { switch (day) { case DayOfWeek.Saturday: case DayOfWeek.Sunday: return "Weekend"; case DayOfWeek.Monday: return "Start of Week"; default: return "Weekday"; } } // switch表达式 string GetDayTypeModern(DayOfWeek day) => day switch { DayOfWeek.Saturday or DayOfWeek.Sunday => "Weekend", // C# 9.0 逻辑模式 DayOfWeek.Monday => "Start of Week", _ => "Weekday" // _ 是丢弃模式,匹配任何其他情况 };</pre>
登录后复制
</div><p><strong>2. 模式匹配的种类</strong></p> <p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式和<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句(从C# 7.0开始)都可以使用多种模式:</p> <ul> <li> <p><strong>类型模式(Type Pattern - C# 7.0)</strong> 用于检查表达式的运行时类型,并将其转换为该类型的新变量。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>object data = "Hello, C#!"; string result = data switch { string s => $"这是一个字符串,长度是 {s.Length}", int i => $"这是一个整数,值为 {i}", _ => "未知类型" }; // 也可以在传统的switch语句中使用: // if (data is string s) { /* ... */ }</pre>
登录后复制
</div></li> <li> <p><strong><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">var</pre>
登录后复制
</div>模式(Var Pattern - C# 7.0)</strong> 匹配任何非<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>值,并将其绑定到一个新的局部变量。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>object item = new List<int> { 1, 2 }; string description = item switch { var list when list is List<int> => $"这是一个整数列表,包含 {((List<int>)list).Count} 个元素", _ => "其他类型" }; // 注意:var模式通常与when子句结合使用,否则它会匹配所有非null值。</pre>
登录后复制
</div></li> <li> <p><strong>属性模式(Property Pattern - C# 8.0)</strong> 允许你根据对象的属性值进行匹配。这在处理复杂对象时特别有用。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>record Order(int OrderId, decimal Amount, string Status); Order order = new(101, 150.75m, "Processing"); string orderStatusMessage = order switch { { Status: "Processing", Amount: > 100m } => "大额订单正在处理中。", { Status: "Completed" } => "订单已完成。", { Status: "Cancelled", OrderId: var id } => $"订单 {id} 已取消。", _ => "未知订单状态。" };</pre>
登录后复制
</div></li> <li> <p><strong>位置模式(Positional Pattern - C# 8.0)</strong> 用于匹配支持解构(Deconstruct)的对象。你可以根据解构后的值进行匹配。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>record Point(int X, int Y); // records 默认支持解构 Point p = new(10, 20); string pointDescription = p switch { (0, 0) => "原点", (> 0, > 0) => "第一象限", (int x, int y) when x < 0 && y > 0 => "第二象限", // 结合when子句 _ => "其他位置" };</pre>
登录后复制
</div></li> <li> <p><strong>关系模式(Relational Pattern - C# 9.0)</strong> 允许你使用关系运算符(<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;"><</pre>
登录后复制
</div>, <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">></pre>
登录后复制
</div>, <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;"><=</pre>
登录后复制
</div>, <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">>=</pre>
登录后复制
</div>)直接在模式中比较值。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>int temperature = 25; string weatherAdvice = temperature switch { < 0 => "极寒,注意保暖!", >= 0 and < 10 => "寒冷,多穿衣服。", // C# 9.0 逻辑模式结合 >= 10 and < 25 => "舒适宜人。", >= 25 and < 35 => "炎热,注意防晒。", _ => "酷暑,避免外出!" };</pre>
登录后复制
</div></li> <li> <p><strong>逻辑模式(Logical Pattern - C# 9.0)</strong> 使用<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">and</pre>
登录后复制
</div>、<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">or</pre>
登录后复制
</div>、<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">not</pre>
登录后复制
</div>运算符组合其他模式,创建更复杂的匹配条件。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>bool IsWorkingDay(DayOfWeek day) => day switch { DayOfWeek.Saturday or DayOfWeek.Sunday => false, not DayOfWeek.Friday => true, // 除了周五以外的工作日 _ => true // 周五也是工作日 };</pre>
登录后复制
</div></li> </ul> <p>这些模式可以灵活组合,形成非常强大和富有表达力的匹配逻辑。在我看来,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式和模式匹配的引入,是C#在处理复杂条件分支方面的一次质的飞跃,它让代码不仅更短,而且更容易理解。</p> <h3><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式与<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句有何不同,我该如何选择?</h3> <p>在我个人的编程实践中,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式和<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句虽然都叫<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>,但它们的设计哲学和应用场景是截然不同的。简单来说,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句更多地是用来执行一系列操作或副作用,而<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式则专注于计算并返回一个单一的结果。</p> <p>传统的<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句(C# 7.0及更早版本)更像是一个控制流结构。你可以在每个<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">case</pre>
登录后复制
</div>块中写多行代码,执行数据库操作、日志记录、UI更新等等,并且需要<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">break</pre>
登录后复制
</div>来防止“穿透”(fall-through)。它不直接返回一个值,而是通过修改外部变量或执行某些动作来达成目的。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>// switch 语句:执行副作用 void ProcessCommand(string command) { switch (command) { case "start": Console.WriteLine("Starting service..."); // 更多启动逻辑 break; case "stop": Console.WriteLine("Stopping service..."); // 更多停止逻辑 break; default: Console.WriteLine("Unknown command."); break; } }</pre>
登录后复制
</div><p>而<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式(C# 8.0引入)则是一个真正的表达式,它必须计算并返回一个值。它的语法更紧凑,通常每个模式后面直接跟着一个<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">=></pre>
登录后复制
</div>和要返回的值。它天然地避免了穿透问题,因为每个分支都必须提供一个结果,并且整个表达式最终会有一个确定的返回值。这让它在处理映射、转换或根据不同输入返回不同配置等场景时,显得异常简洁。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>// switch 表达式:计算并返回一个值 string GetServiceStatus(ServiceState state) => state switch { ServiceState.Running => "Service is active.", ServiceState.Stopped => "Service is inactive.", ServiceState.Error => "Service encountered an error.", _ => "Unknown service state." };</pre>
登录后复制
</div><p><strong>如何选择?</strong></p> <p>我的经验是:</p> <ol> <li> <strong>如果你需要根据输入值执行不同的“动作”或“副作用”(如打印日志、修改状态、调用其他方法),并且这些动作本身不直接返回一个有用的值供后续使用,那么<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句是更合适的选择。</strong> 它提供了更大的自由度来编写多行逻辑。</li> <li> <strong>如果你需要根据输入值“计算”或“映射”出一个结果,并且这个结果会立即被后续代码使用,那么<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式无疑是更优的选择。</strong> 它能够将复杂的条件逻辑浓缩成一行或几行,极大地提高了代码的简洁性和可读性。在很多情况下,它能替代冗长的<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">if-else if</pre>
登录后复制
</div>链,让代码意图一目了然。</li> </ol> <p>当然,两者并非完全互斥。有时候,你可能在<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式的某个分支中,还需要调用一个执行副作用的方法。但总体原则是,关注你最终想要的是一个“动作”还是一“结果”。</p> <h3>C#模式匹配在实际开发中能解决哪些常见的痛点?</h3> <p>在我看来,C#的模式匹配并非仅仅是语法上的“锦上添花”,它实实在在地解决了许多在日常开发中遇到的痛点,让代码变得更具弹性、更安全,也更容易维护。</p> <ol> <li> <p><strong>处理多态类型集合时的繁琐判断:</strong> 想象一下,你有一个<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">List<object></pre>
登录后复制
</div>,里面混合了各种类型的对象(字符串、整数、自定义类)。传统上,你需要写一堆<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">if (obj is TypeA a) { ... } else if (obj is TypeB b) { ... }</pre>
登录后复制
</div>。这不仅冗长,而且容易遗漏<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">else</pre>
登录后复制
</div>分支,导致逻辑不完整。 <strong>模式匹配的解决方案:</strong></p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>List<object> items = new() { 10, "hello", new DateTime(2023, 1, 1), 3.14f }; foreach (var item in items) { string description = item switch { int i => $"整数: {i}", string s => $"字符串: '{s}' ({s.Length} chars)", DateTime dt => $"日期: {dt.ToShortDateString()}", float f => $"浮点数: {f:F2}", _ => "未知类型" }; Console.WriteLine(description); }</pre>
登录后复制
</div><p>这让处理异构集合变得异常优雅,代码结构清晰,且编译器能帮助检查是否覆盖了所有可能的类型(对于<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式)。</p> </li> <li> <p><strong>复杂的业务规则或状态机逻辑:</strong> 当你的业务逻辑涉及到多个条件组合时,比如一个订单的状态、金额、用户等级等共同决定某个操作的权限或结果,传统的<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">if-else if</pre>
登录后复制
</div>会迅速膨胀成“意大利面条”式的代码。 <strong>模式匹配的解决方案:</strong> 利用属性模式、关系模式和逻辑模式,可以清晰地表达这些复杂的组合条件。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>record User(string Name, UserRole Role, bool IsActive); record Order(int Id, decimal Amount, OrderStatus Status); enum UserRole { Guest, Member, Admin } enum OrderStatus { Pending, Processing, Completed, Cancelled } bool CanProcessOrder(User user, Order order) => (user, order) switch { ({ Role: UserRole.Admin }, _) => true, // 管理员可以处理任何订单 ({ IsActive: true, Role: UserRole.Member }, { Status: OrderStatus.Pending or OrderStatus.Processing, Amount: <= 1000m }) => true, // 活跃会员可以处理小额待处理或处理中订单 ({ IsActive: false }, _) => false, // 非活跃用户不能处理 (_, { Status: OrderStatus.Completed or OrderStatus.Cancelled }) => false, // 已完成或已取消的订单不能再处理 _ => false // 其他情况均不能处理 };</pre>
登录后复制
</div><p>这种方式将复杂的条件判断逻辑集中在一个地方,并且可读性极高,一眼就能看出不同组合下的行为。</p> </li> <li> <p><strong>空值(null)检查的简化:</strong> 虽然C# 8.0引入了可空引用类型,但显式的<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>检查依然是必要的。模式匹配可以很自然地融入<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>检查。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>object? value = null; // 或者 new object(); string info = value switch { null => "值为空。", string s => $"这是一个字符串:{s}", _ => "非空但非字符串。" };</pre>
登录后复制
</div><p>这避免了单独写<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">if (value is null)</pre>
登录后复制
</div>的语句,让逻辑更加紧凑。</p> <div class="aritcle_card"> <a class="aritcle_card_img" href="/ai/1511"> <img src="https://img.php.cn/upload/ai_manual/000/969/633/68b7a3574b022434.png" alt="文心大模型"> </a> <div class="aritcle_card_info"> <a href="/ai/1511">文心大模型</a> <p>百度飞桨-文心大模型 ERNIE 3.0 文本理解与创作</p> <div class=""> <img src="/static/images/card_xiazai.png" alt="文心大模型"> <span>168</span> </div> </div> <a href="/ai/1511" class="aritcle_card_btn"> <span>查看详情</span> <img src="/static/images/cardxiayige-3.png" alt="文心大模型"> </a> </div> </li> </ol> <p>模式匹配的这些能力,让我在编写业务逻辑时,能够更专注于“数据是什么样子”,而不是“如何一步步判断它”,从而写出更声明式、更易于理解和维护的代码。</p> <h3>深入理解C#模式匹配的执行顺序和潜在陷阱</h3> <p>模式匹配虽然强大,但在使用时,如果不了解其执行顺序和一些潜在的“坑”,可能会导致意料之外的行为。我个人在实践中就遇到过一些情况,所以深入理解这些细节非常重要。</p> <p><strong>1. 模式的执行顺序</strong></p> <p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式或<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>语句中的模式是<strong>从上到下、按顺序评估</strong>的。这意味着,一旦一个模式匹配成功,其对应的表达式或代码块就会被执行,并且后续的模式将不再被评估。这是一个非常关键的规则。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>object data = 100; string result = data switch { int i => "匹配到 int 类型", // 会匹配到这里 > 50 => "匹配到大于 50 的值", // 这行永远不会被匹配到,因为它在 int i 之后 _ => "其他" }; Console.WriteLine(result); // 输出: 匹配到 int 类型</pre>
登录后复制
</div><p>在这个例子中,即使<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">100</pre>
登录后复制
</div>也满足<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">> 50</pre>
登录后复制
</div>的条件,但因为<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">int i</pre>
登录后复制
</div>模式在它之前且已经匹配成功,所以<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">> 50</pre>
登录后复制
</div>的模式就“失效”了。因此,编写模式时,<strong>更具体的、更严格的模式应该放在前面,而更通用的、更宽泛的模式应该放在后面。</strong></p> <p><strong>2. 编译器的穷尽性检查(Exhaustiveness Checking)</strong></p> <p>对于<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式,C#编译器会尝试进行穷尽性检查。这意味着,如果你的<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式没有覆盖所有可能的输入值,编译器会发出警告,甚至在某些情况下(如处理枚举类型时),会直接报错。这是一个非常棒的安全特性,它强制你考虑所有可能的场景,避免了运行时因未处理情况而导致的错误。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>// 假设有一个枚举 enum TrafficLight { Red, Yellow, Green } TrafficLight light = TrafficLight.Red; string action = light switch { TrafficLight.Red => "Stop", // 如果这里缺少 Yellow 或 Green,编译器会警告甚至报错,因为它不是穷尽的 _ => "Proceed" // _ 模式可以作为捕获所有未显式处理情况的最终手段 };</pre>
登录后复制
</div><p>但需要注意的是,对于<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">object</pre>
登录后复制
</div>类型或其他开放类型,编译器很难知道所有可能的派生类,所以穷尽性检查会依赖于<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">_</pre>
登录后复制
</div>(discard pattern)来确保所有情况都被覆盖。</p> <p><strong>3. <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">when</pre>
登录后复制
</div>子句与模式的结合</strong></p> <p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">when</pre>
登录后复制
</div>子句允许你在模式匹配成功后,添加额外的条件。这个条件是在模式匹配成功后才评估的。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>int value = 15; string category = value switch { int i when i < 10 => "小于10", int i when i >= 10 && i < 20 => "10到19之间", // 会匹配到这里 int i => "大于等于20", _ => "其他" }; Console.WriteLine(category); // 输出: 10到19之间</pre>
登录后复制
</div><p>这里,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">int i</pre>
登录后复制
</div>模式本身会匹配所有整数,但<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">when</pre>
登录后复制
</div>子句进一步筛选了条件。如果第一个<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">when</pre>
登录后复制
</div>子句不满足,则会继续尝试下一个<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">int i when ...</pre>
登录后复制
</div>。</p> <p><strong>4. <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>值的处理</strong></p> <p>模式匹配对<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>值有特殊的处理。一个模式(除了<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>模式本身)通常不会匹配<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:csharp;toolbar:false;'>object? item = null; string description = item switch { string s => "字符串", // 不会匹配null int i => "整数", // 不会匹配null null => "空值", // 专门匹配null _ => "其他非空类型" // 匹配所有非null且未被前面模式匹配的类型 }; Console.WriteLine(description); // 输出: 空值</pre>
登录后复制
</div><p>如果你不显式处理<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>,并且<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">item</pre>
登录后复制
</div>是<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>,那么它会跳过所有非<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">null</pre>
登录后复制
</div>模式,最终可能由<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">_</pre>
登录后复制
</div>模式捕获,或者如果<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">_</pre>
登录后复制
</div>模式也不存在,<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">switch</pre>
登录后复制
</div>表达式会抛出<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">System.Runtime.CompilerServices.SwitchExpressionException</pre>
登录后复制
</div>。</p> <p><strong>5. 潜在的性能考量</strong></p> <p>虽然编译器对模式匹配进行了大量优化,但在极端复杂的模式组合下,尤其是涉及大量属性模式和<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">when</pre>
登录后复制
</div>子句时,可能会有轻微的性能开销。不过,对于绝大多数日常应用,这种开销可以忽略不计,模式匹配带来的代码清晰度和安全性收益远大于此。如果真的遇到性能瓶颈,通常是算法或数据结构层面的问题,而不是模式匹配本身。</p> <p>总而言之,模式匹配是C#语言的一个巨大进步,但理解其内在机制,特别是模式的评估顺序和穷尽性检查,能帮助我们写出更健壮、更可预测的代码。在遇到不符合预期的情况时,首先检查模式的顺序,往往能找到问题的根源。</p>

以上就是C#的switch语句有哪些新特性?如何模式匹配?的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号