閱讀本文大概需要 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 語句的增強,可以支援實現複雜的條件匹配。下面我先用一個示例來展示一下模式匹配的一般的用法。
假如現在我們要計算各種車輛在某高速的通行費,比如有下面四種車輛,分別定義為以下四個類,各個類中定義了和通行費計算相關的屬性:
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; }
}
下面用用模式匹配的方式來實現一個計算通行費的方法:
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
方法示例程式碼為例,簡單模式是這種:
vehicle switch
{
...
Car c => 2.00m - 1.0m
}
我們其實可以發現,上面的變數 c
宣告瞭卻沒用被使用,現在 C# 9.0 中可以把它省略了:
vehicle switch
{
...
Car => 2.00m - 1.0m
}
關係模式
以上面 CalculateToll
方法示例程式碼為例,關係模式是通過比較(大小)關係來匹配的,對應的程式碼片段如下:
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 可以簡寫成:
DeliveryTruck t when t.GrossWeightClass switch
{
> 5000 => 10.00m + 5.00m,
< 3000 => 10.00m - 2.00m,
_ => 10.00m,
}
邏輯模式
在 C# 9.0 中,你可以通過邏輯操作符 and
、or
和 not
對模式進行組合,下面是一些示例:
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 條件判斷中的邏輯非(!),比如:
// 原來的寫法
if (!(e is Customer)) { ... }
// 新的寫法(易讀性更好)
if (e is not Customer) { ... }
C# 9.0 還有很多其它好用的新特性,下一篇文章繼續與你分享。文章寫短一點不是因為我偷懶哈,而是為了促使大家一次性看完,方便大家在零碎時間閱讀,避免因文章太長而成為“收藏不看”系列。
敬請關注我明天下一篇關於 C# 9.0 新特性的介紹,明天不見不散。
參考: