【C#9.0篇】Switch匹配模式新特性

发布时间 2023-10-22 14:04:46作者: Harley-Chang

概述

C#9.0中的switch 匹配模式引入了许多新特性,其中一些特性是C#8.0中不存在的,比如以下特性:

  • 关系模式:可以使用关系运算符
  • 模式匹配+逻辑模式:可以使用模式匹配+逻辑模式(如and、or)来组合多个模式
  • 模式匹配+关系模式:可以使用模式匹配+关系运算符(如<、>、<=、>=、==、!=)
  • 默认的匹配不必使用丢弃“_”来实现
    下面我们举例说明一下这些特性:

示例

下面我将使用dotnet cli 创建一个dotnet 6.0的项目。

环境信息

Platform:Windows 11

Dotnet SDK:6.0

IDE:VS Code

首先我们按照以下步骤创建项目:

步骤一:创建项目文件夹

mkdir CSharp9.ChapterSwitch.Sample
cd CSharp9.ChapterSwitch.Sample

步骤二:创建项目文件

dotnet new sln -n CSharp9.ChapterSwitch.Sample
mkdir src
cd src

步骤三:创建类库以及控制台

dotnet new console -n CSharp9.ChapterSwitch.Console --framework net6.0
dotnet new classlib -n CSharp9.ChapterSwitch.Models --framework net6.0

步骤四:将类库以及控制台添加到项目上

cd ..
dotnet sln add src/CSharp9.ChapterSwitch.Console/CSharp9.ChapterSwitch.Console.csproj
dotnet sln add src/CSharp9.ChapterSwitch.Models/CSharp9.ChapterSwitch.Models.csproj
dotnet add src/CSharp9.ChapterSwitch.Console/CSharp9.ChapterSwitch.Console.csproj reference src/CSharp9.ChapterSwitch.Models/CSharp9.ChapterSwitch.Models.csproj

步骤五:示例代码

1、Models 类库代码

在Models类库中,按照以下代码片段添加相关的类文件,请注意类的命名空间

fragment 1

namespace CSharp9.ChapterSwitch.Models;
public class Electronic
{
    public double Price { get; set; }
    public string Name { get; set; }
}
namespace CSharp9.ChapterSwitch.Models;
public class MobilePhone : Electronic
{
}
namespace CSharp9.ChapterSwitch.Models;
public class Camera : Electronic
{
    public double Pixel { get; set; }
}
namespace CSharp9.ChapterSwitch.Models;
public class Computer : Electronic
{
    public int LightingInterface { get; set; }
}

2、Console 代码

在Console控制台的Program中添加 code fragment2的代码片段

fragment 2

using CSharp9.ChapterSwitch.Models;
using System;

class Program
{
    static void Main(string[] args)
    {
        SwitchExpression();
    }

    static void SwitchExpression()
    {
        Electronic[] electronics =
        {
            new MobilePhone{Name="XIAOMI5",Price=5000},
            new MobilePhone{Name="IPhone13Pro",Price=9000},
            new MobilePhone{Name="HUAWEIMate50Pro",Price=7000},
            new MobilePhone{Name="HUAWEIP50Pro",Price=8000},
            new Camera{Name="Canon80D",Price=7000,Pixel=12000_000},
            new Computer{Name="DELLXPS7590",Price=8600,LightingInterface=1},
            new Computer{Name="DELLXPS9360",Price=12000,LightingInterface=3}
        };

        foreach (var electronic in electronics)
        {
             {
                //c#8.0
                var desc = electronic switch
                {
                    MobilePhone s => s.Price switch
                    {
                        double a when a <= 5000 => "Cost performance electronic",
                        double a when a <= 7000 => "Slightly expensive electronic",
                        double a when a <= 9000 => "Light luxury electronic",
                        _ => "Other"
                    },
                    Camera s when s.Price <= 7000 && s.Pixel <= 12000_000 => "Cost performance electronic",
                    Camera _ => "Other",
                    Computer s when s.Price <= 7000 && s.LightingInterface >= 1 => "Cost performance electronic",
                    Computer s when s.Price <= 10000 && s.LightingInterface >= 2 => "Slightly expensive electronic",
                    Computer s when s.Price <= 12000 && s.LightingInterface >= 3 => "Light luxury electronic",
                    Computer _ => "Other",
                    _ => throw new NotImplementedException()
                };
                Console.WriteLine($"Current electronic is {electronic.Name},price:{electronic.Price:C},is {desc}.");
            }
        }
        
        Console.Read();
    }
}

3、Console 项目设置

fragment 3

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>disable</ImplicitUsings>
    <Nullable>disable</Nullable>
    <LangVersion>8</LangVersion>
</PropertyGroup>

运行代码:

dotnet run --project src/CSharp9.ChapterSwitch.Console/CSharp9.ChapterSwitch.Console.csproj

如上例,有一个 Electronic父类,Mobile、Camera、Computer分别继承Electronic类,并且每个自类有可能有自己单独的属性,然后在Program中声明一个Electronic数组,并且循环输出信息,循环判断并输出当前电子产品的定位,性价比、稍贵、轻奢品

以上Console中的Program是使用的C#8.0的语法编写Switch的匹配模式,下面我们使用C#9.0的Switch匹配模式新特性来重构这段代码:

4、匹配模式新特性

设置Console.csproj的 LangVersion=9,重构以上Console中代码,重新运行项目

fragment 4

using CSharp9.ChapterSwitch.Models;
using System;

class Program
{
    static void Main(string[] args)
    {
        SwitchExpression();
    }

    static void SwitchExpression()
    {
        Electronic[] electronics =
        {
            new MobilePhone{Name="XIAOMI5",Price=5000},
            new MobilePhone{Name="IPhone13Pro",Price=9000},
            new MobilePhone{Name="HUAWEIMate50Pro",Price=7000},
            new MobilePhone{Name="HUAWEIP50Pro",Price=8000},
            new Camera{Name="Canon80D",Price=7000,Pixel=12000_000},
            new Computer{Name="DELLXPS7590",Price=8600,LightingInterface=1},
            new Computer{Name="DELLXPS9360",Price=12000,LightingInterface=3}
        };

        Console.WriteLine($"C# 8.0");
        foreach (var electronic in electronics)
        {
            {
                //c#8.0
                var desc = electronic switch
                {
                    MobilePhone s => s.Price switch
                    {
                        double a when a <= 5000 => "Cost performance electronic",
                        double a when a <= 7000 => "Slightly expensive electronic",
                        double a when a <= 9000 => "Light luxury electronic",
                        _ => "Other"
                    },
                    Camera s when s.Price <= 7000 && s.Pixel <= 12000_000 => "Cost performance electronic",
                    Camera _ => "Other",
                    Computer s when s.Price <= 7000 && s.LightingInterface >= 1 => "Cost performance electronic",
                    Computer s when s.Price <= 10000 && s.LightingInterface >= 2 => "Slightly expensive electronic",
                    Computer s when s.Price <= 12000 && s.LightingInterface >= 3 => "Light luxury electronic",
                    Computer _ => "Other",
                    _ => throw new NotImplementedException()
                };
                Console.WriteLine($"Current electronic is {electronic.Name},price:{electronic.Price:C},is {desc}.");
            }

        };

        Console.WriteLine($"C# 9.0 写法1");
        foreach (var electronic in electronics)
        {
            {
                // c#9.0 写法1
                var desc = electronic switch
                {
                    MobilePhone s => s.Price switch //关系模式
                    {
                        <= 5000 => "Cost performance electronic",
                        <= 7000 => "Slightly expensive electronic",
                        <= 9000 => "Light luxury electronic",
                        _ => "Other"
                    },
                    Camera { Price: <= 7000, Pixel: <= 12000_000 } => "Cost performance electronic", // 模式变量+关系模式
                    Camera => "Other",// 无需丢弃"_"
                    Computer { Price: <= 7000, LightingInterface: >= 1 } => "Cost performance electronic",
                    Computer { Price: <= 10000, LightingInterface: >= 2 } => "Slightly expensive electronic",
                    Computer { Price: <= 12000, LightingInterface: >= 3 } => "Light luxury electronic",
                    Computer => "Other",
                    _ => throw new NotImplementedException()
                };
                Console.WriteLine($"Current electronic is {electronic.Name},price:{electronic.Price:C},is {desc}.");
            }

        };

        Console.WriteLine($"C# 9.0 写法2");
        foreach (var electronic in electronics)
        {
            {
                // c#9.0 写法2
                var desc = electronic switch
                {
                    MobilePhone { Price: <= 5000 } or Camera { Price: <= 7000, Pixel: <= 12000_000 } or Computer { Price: <= 7000, LightingInterface: >= 1 } => "Cost performance electronic",//模式变量+关系模式+逻辑或
                    MobilePhone s => s.Price switch 
                    {
                        <= 5000 => "Cost performance electronic",
                        <= 7000 => "Slightly expensive electronic",
                        <= 9000 => "Light luxury electronic",
                        _ => "Other"
                    },
                    Camera => "Other",
                    Computer { Price: <= 10000 } and Computer { LightingInterface: >= 2 } => "Slightly expensive electronic", //模式变量+关系模式+逻辑与
                    Computer { Price: <= 12000 } and Computer { LightingInterface: >= 3 } => "Light luxury electronic",
                    Computer => "Other",
                    _ => throw new NotImplementedException()
                };
                Console.WriteLine($"Current electronic is {electronic.Name},price:{electronic.Price:C},is {desc}.");
            }
        }
        Console.Read();
    }
}

重新运行代码

dotnet run --project src/CSharp9.ChapterSwitch.Console/CSharp9.ChapterSwitch.Console.csproj