zoukankan      html  css  js  c++  java
  • 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(预览版)

        

  • 相关阅读:
    Azkaban的使用
    Azkaban安装
    Kafka 启动失败,报错Corrupt index found以及org.apache.kafka.common.protocol.types.SchemaException: Error reading field 'version': java.nio.BufferUnderflowException
    Kafka 消费者设置分区策略及原理
    Kafka利用Java API自定义生产者,消费者,拦截器,分区器等组件
    zookeeper群起总是有那么几个节点起不来的问题解决
    flume 启动agent报No appenders could be found for logger的解决
    Flume 的监控方式
    Flume 自定义 组件
    Source r1 has been removed due to an error during configuration java.lang.IllegalArgumentException: Required parameter bind must exist and may not be null & 端口无法连接
  • 原文地址:https://www.cnblogs.com/leehomlee/p/15160443.html
Copyright © 2011-2022 走看看