模式
-
- is 表达式
-
switch
语句
-
switch
表达式(C# 8.0 引入)
在这些构造中,可将输入表达式与以下任一模式进行匹配:
-
- 声明模式:用于检查表达式的运行时类型,如果匹配成功,则将表达式结果分配给声明的变量。 在 C# 7.0 中引入。
- 类型模式:用于检查表达式的运行时类型。 在 C# 9.0 中引入。
- 常量模式:用于测试表达式结果是否等于指定常量。 在 C# 7.0 中引入。
- 关系模式:用于将表达式结果与指定常量进行比较。 在 C# 9.0 中引入。
- 逻辑模式:用于测试表达式是否与模式的逻辑组合匹配。 在 C# 9.0 中引入。
- 属性模式:用于测试表达式的属性或字段是否与嵌套模式匹配。 在 C# 8.0 中引入。
- 位置模式:用于解构表达式结果并测试结果值是否与嵌套模式匹配。 在 C# 8.0 中引入。
-
var
模式:用于匹配任何表达式并将其结果分配给声明的变量。 在 C# 7.0 中引入。 - 弃元模式:用于匹配任何表达式。 在 C# 8.0 中引入。
模式匹配
- C# 7.0 - 7.3
模式匹配支持 is
表达式和 switch
表达式。
以下代码检查变量是否为 int
,如果是,则将其添加到当前总和:
if (input is int count) sum += count;
更新后的 switch 语句有几个新构造:
-
- switch 表达式的控制类型不再局限于整数类型、
Enum
类型、string
或与这些类型之一对应的可为 null 的类型。可能会使用任何类型。 - 可以在每个
case
标签中测试switch
表达式的类型。 与is
表达式一样,可以为该类型指定一个新变量。 - 可以添加
when
子句以进一步测试该变量的条件。 -
case
标签的顺序现在很重要。 执行匹配的第一个分支;其他将跳过。
- switch 表达式的控制类型不再局限于整数类型、
public static int SumPositiveNumbers(IEnumerable<object> sequence) { int sum = 0; foreach (var i in sequence) { switch (i) { case 0: break; case IEnumerable<int> childSequence: { foreach(var item in childSequence) sum += (item > 0) ? item : 0; break; } case int n when n > 0: sum += n; break; case null: throw new NullReferenceException("Null found in sequence"); default: throw new InvalidOperationException("Unrecognized type"); } } return sum; }
- C# 8.0
switch 表达式
更简洁的表达式语法
下面以 彩虹颜色 枚举举例
public enum Rainbow { Red, Orange, Yellow, Green, Blue, Indigo, Violet }
如果应用定义了通过 R
、G
和 B
组件构造而成的 RGBColor
类型,可使用以下包含 switch 表达式的方法,将 Rainbow
转换为 RGB 值:
public static RGBColor FromRainbow(Rainbow colorBand) => colorBand switch { Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00), Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00), Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00), Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00), Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF), Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82), Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3), _ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)), };
这里有几个语法改进:
-
- 变量位于
switch
关键字之前。 不同的顺序使得在视觉上可以很轻松地区分 switch 表达式和 switch 语句。 - 将
case
和:
元素替换为=>
。 它更简洁,更直观。 - 将
default
事例替换为_
弃元。 - 正文是表达式,不是语句。
- 变量位于
属性模式
下面使用属性模式从地址和价格计算销售税:
State 是 地址Address 的一个属性。
public static decimal ComputeSalesTax(Address location, decimal salePrice) => location switch { { State: "WA" } => salePrice * 0.06M, { State: "MN" } => salePrice * 0.075M, { State: "MI" } => salePrice * 0.05M, // other cases removed for brevity... _ => 0M };
元组模式
以下代码显示了游戏“rock, paper, scissors(石头剪刀布)”的切换表达式:
public static string RockPaperScissors(string first, string second) => (first, second) switch { ("rock", "paper") => "rock is covered by paper. Paper wins.", ("rock", "scissors") => "rock breaks scissors. Rock wins.", ("paper", "rock") => "paper covers rock. Paper wins.", ("paper", "scissors") => "paper is cut by scissors. Scissors wins.", ("scissors", "rock") => "scissors is broken by rock. Rock wins.", ("scissors", "paper") => "scissors cuts paper. Scissors wins.", (_, _) => "tie" };
位置模式
暂无
- C# 9.0
模式匹配改进:
-
- 类型模式要求在变量是一种类型时匹配
- 带圆括号的模式强制或强调模式组合的优先级
- 联合
and
模式要求两个模式都匹配 - 析取
or
模式要求任一模式匹配 - 否定
not
模式要求模式不匹配 - 关系模式要求输入小于、大于、小于等于或大于等于给定常数。
public static bool IsLetter(this char c) => c is >= ‘a‘ and <= ‘z‘ or >= ‘A‘ and <= ‘Z‘;
public static bool IsLetterOrSeparator(this char c) => c is (>= ‘a‘ and <= ‘z‘) or (>= ‘A‘ and <= ‘Z‘) or ‘.‘ or ‘,‘;
if (e is not null) { // ... }
类型模式示例:
public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch { Car => 2.00m, Truck => 7.50m, null => throw new ArgumentNullException(nameof(vehicle)), _ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)), };
- C# 10.0(预览版)