1. 程式人生 > >C# 9.0 新特性之模式匹配簡化

C# 9.0 新特性之模式匹配簡化

閱讀本文大概需要 2 分鐘。

記得在 MS Build 2020 大會上,C# 語言開發專案經理 Mads Torgersen 宣稱 C# 9.0 將會隨著 .NET 5 在今年 11 月份正式釋出。目前 .NET 5 已經到了 Preview 5 階段了,C# 9.0 也已經初具規模。忍不住激動的心情,暫停更新《C#.NET 拾遺補漏》系列幾天,先要和大家分享一下我瞭解到的 C# 9.0 的新特性。由於新特性比較多,所以會分成幾篇來講。這是第一篇,專講模式匹配這個特性的簡化。 模式匹配(Pattern Matching)是在 C# 7.0 引入的,是對 switch 語句的增強,可以支援實現複雜的條件匹配。下面我先用一個示例來展示一下模式匹配的一般的用法。 假如現在我們要計算各種車輛在某高速的通行費,比如有下面四種車輛,分別定義為以下四個類,各個類中定義了和通行費計算相關的屬性: ```cs public class Car { public int Passengers { get; set; } } public class DeliveryTruck { public int GrossWeightClass { get; set; } } public class Taxi { public int Fares { get; set; } } public class Bus { public int Capacity { get; set; } public int Riders { get; set; } } ``` 下面用用模式匹配的方式來實現一個計算通行費的方法: ```cs public decimal CalculateToll(object vehicle) =>
vehicle switch { Car { Passengers: 0} => 2.00m + 0.50m, Car { Passengers: 1} => 2.0m, Car { Passengers: 2} => 2.0m - 0.50m, Car c => 2.00m - 1.0m, Taxi t => t.Fares switch { 0 => 3.50m + 1.00m, 1 => 3.50m, 2 => 3.50m - 0.50m, _ =>
3.50m - 1.00m }, Bus b when ((double)b.Riders / (double)b.Capacity) < 0.50 => 5.00m + 2.00m, Bus b when ((double)b.Riders / (double)b.Capacity) > 0.90 => 5.00m - 1.00m, Bus b => 5.00m, DeliveryTruck t when (t.GrossWeightClass > 5000) => 10.00m + 5.00m, DeliveryTruck t when (t.GrossWeightClass < 3000) => 10.00m - 2.00m, DeliveryTruck _ => 10.00m, { } => throw new ArgumentException(message: "Not a known vehicle type", paramName: nameof(vehicle)), null => throw new ArgumentNullException(nameof(vehicle)) }; ```

程式碼來源於文末參考連結

如果上面程式碼閱讀起來感覺吃力,你可以先閱讀文末參考連結中的第一個連結,關於模式匹配的詳細介紹。 實現這個業務邏輯,若在 C# 7.0 之前,需要用一堆的 if/else 來實現。有了模式匹配後,變得方便了很多,而且使用上很靈活,程式碼結構也更優美。 對我來說,模式匹配是個極好的特性!但這還不夠,C# 9.0 對模式匹配的寫法做了進一步的簡化! 以上面程式碼為例,模式匹配可以分為三種:簡單模式、關係模式和邏輯模式。下面分別說說 C# 9.0 對三種模式的簡化。 ### 簡單模式 以上面 `CalculateToll` 方法示例程式碼為例,簡單模式是這種: ```cs vehicle switch { ... Car c => 2.00m - 1.0m } ``` 我們其實可以發現,上面的變數 `c` 聲明瞭卻沒用被使用,現在 C# 9.0 中可以把它省略了: ```cs vehicle switch { ... Car => 2.00m - 1.0m } ``` ### 關係模式 以上面 `CalculateToll` 方法示例程式碼為例,關係模式是通過比較(大小)關係來匹配的,對應的程式碼片段如下: ```cs DeliveryTruck t when (t.GrossWeightClass > 5000) => 10.00m + 5.00m, DeliveryTruck t when (t.GrossWeightClass < 3000) => 10.00m - 2.00m, DeliveryTruck _ => 10.00m, ``` 現在 C# 9.0 可以簡寫成: ```cs DeliveryTruck t when t.GrossWeightClass switch { > 5000 => 10.00m + 5.00m, < 3000 => 10.00m - 2.00m, _ => 10.00m, } ``` ### 邏輯模式 在 C# 9.0 中,你可以通過邏輯操作符 `and`、`or` 和 `not` 對模式進行組合,下面是一些示例: ```cs DeliveryTruck t when t.GrossWeightClass switch { < 3000 => 10.00m - 2.00m, >= 3000 and <= 5000 => 10.00m, > 5000 => 10.00m + 5.00m, } not null => throw new ArgumentException($"Not a known vehicle type: {vehicle}", nameof(vehicle)), null => throw new ArgumentNullException(nameof(vehicle)) ``` 另外,`not` 關鍵字還可以用來替代 if 條件判斷中的邏輯非(!),比如: ```cs // 原來的寫法 if (!(e is Customer)) { ... } // 新的寫法(易讀性更好) if (e is not Customer) { ... } ``` C# 9.0 還有很多其它好用的新特性,下一篇文章繼續與你分享。文章寫短一點不是因為我偷懶哈,而是為了促使大家一次性看完,方便大家在零碎時間閱讀,避免因文章太長而成為“收藏不看”系列。 敬請關注我明天下一篇關於 C# 9.0 新特性的介紹,明天不見不散。 >參考: >1. https://bit.ly/2MNc0DJ >2. https://bit.ly/