模式匹配
模式匹配性能更好,因为 C# 编译器会根据你的模式编译出最优的匹配路径。
switch 表达式
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)), };
属性模式
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 };
元组模式
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" };
位置模式
某些类型包含 Deconstruct
方法,该方法将其属性解构为离散变量。
public class Point { public int X { get; } public int Y { get; } public Point(int x, int y) => (X, Y) = (x, y); public void Deconstruct(out int x, out int y) => (x, y) = (X, Y); }
public record Order(int Items, decimal Cost); public decimal CalculateDiscount(Order order) => order switch { ( > 10, > 1000.00m) => 0.10m, ( > 5, > 50.00m) => 0.05m, ( _, Cost: > 250.00m) => 0.02m, null => throw new ArgumentNullException(nameof(order), "Can't calculate discount on null order"), _ => 0m, };
static Quadrant GetQuadrant(Point point) => point switch { (0, 0) => Quadrant.Origin, var (x, y) when x > 0 && y > 0 => Quadrant.One, var (x, y) when x < 0 && y > 0 => Quadrant.Two, var (x, y) when x < 0 && y < 0 => Quadrant.Three, var (x, y) when x > 0 && y < 0 => Quadrant.Four, var (_, _) => Quadrant.OnBorder, _ => Quadrant.Unknown };
列表模式
列表模式提供了一种将模式应用于序列的任何元素的方法。 此外,还可以应用 放弃模式 (_
) 来匹配任何元素,或者应用 切片模式 来匹配零个或多个元素。
public void MatchElements(int[] array) { if (array is [0,1]) { Console.WriteLine("Binary Digits"); } else if (array is [1,1,2,3,5,8, ..]) { Console.WriteLine("array looks like a Fibonacci sequence"); } else { Console.WriteLine("Array shape not recognized"); } }
模式匹配支持递归模式
string QueryMessage(Entry entry) { return entry switch { UserEntry u => dbContext1.User.FirstOrDefault(i => i.Id == u.UserId) switch { null => dbContext2.User.FirstOrDefault(i => i.Id == u.UserId)?.Content ?? "", var found => found.Content }, DataEntry d => dbContext1.Data.FirstOrDefault(i => i.Id == d.DataId) switch { null => dbContext2.Data.FirstOrDefault(i => i.Id == u.DataId)?.Content ?? "", var found => found.Content }, EventEntry { EventId: var eventId, CanRead: true } => dbContext1.Event.FirstOrDefault(i => i.Id == eventId) switch { null => dbContext2.Event.FirstOrDefault(i => i.Id == eventId)?.Content ?? "", var found => found.Content }, EventEntry { CanRead: false } => "", _ => throw new InvalidArgumentException("无效的参数") }; }
C# 9 包括新的模式匹配改进:
- 类型模式 与对象匹配特定类型
- 带圆括号的模式强制或强调模式组合的优先级
- 联合
and
模式要求两个模式都匹配 - 析取
or
模式要求任一模式匹配 - 否定
not
模式要求模式不匹配 - 关系模式要求输入小于、大于、小于等于或大于等于给定常数。
public static bool IsLetter(this char c) => c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';
用于 NULL 检查的新语法:e is not null
string WaterState(int tempInFahrenheit) => tempInFahrenheit switch { (> 32) and (< 212) => "liquid", < 32 => "solid", > 212 => "gas", 32 => "solid/liquid transition", 212 => "liquid / gas transition", };
嵌套属性模式匹配改进
以前在匹配嵌套属性的时候需要这么写:
if (a is { X: { Y: { Z: 4 } } }) { ... }
现在只需要简单的:
if (a is { X.Y.Z: 4 }) { ... }
就可以了。