• C# 模式&模式匹配


      模式

      • 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 标签的顺序现在很重要。 执行匹配的第一个分支;其他将跳过。
    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;
    }
      • case 0: 是常量模式
      • case IEnumerable<int> childSequence: 是声明模式
      • case int n when n > 0: 是具有附加 when 条件的声明模式。
      • case null: 是 null 常量模式。
      • default: 是常见的默认事例。
    • C# 8.0

        switch 表达式

        更简洁的表达式语法

        下面以 彩虹颜色 枚举举例

    public enum Rainbow
    {
        Red,
        Orange,
        Yellow,
        Green,
        Blue,
        Indigo,
        Violet
    }

        如果应用定义了通过 RG 和 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(预览版)

        

  • 相关阅读:
    从 i++ 和 ++i 说起局部变量表和操作数栈
    数据库连接情况查询相关sql语句
    db2相关语句
    BeanUtils源码详解
    Spring注解驱动开发之AOP
    Spring注解驱动开发之IOC
    正则表达式
    linux特殊符号
    linux下面如何让一个软件/命令开机自启动
    linux文件属性
  • 原文地址:https://www.cnblogs.com/leehomlee/p/15160443.html
Copyright © 2020-2023  润新知