C#模式匹配

C#模式匹配起因在C#中模式匹配是通过switch实现的(在c# 7/8是这样的),在C# 7.0新增,在之后C# 7.1/C# 8.0及C# 9.0对模式

大家好,欢迎来到IT知识分享网。

起因

在C#中模式匹配是通过switch实现的(在c# 7/8是这样的),在C# 7.0新增,在之后C# 7.1/C# 8.0及C# 9.0对模式匹配进行了扩展,模式匹配主要是简化控制流程(看起来和使用起来),让代码有更好的可读性.

最早接触模式匹配,是在Rust语言中,在通过Rust中是用match关键字去实现的.

模式匹配 C# 7.0

/// <summary>
/// 官方文档 示例
/// </summary>
/// <param name="sequence"></param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public static int SumPositiveNumbers(IEnumerable<object> sequence)
{
    int sum = 0;
    foreach (var i in sequence)
    {
        switch (i)
        {
            case 0:  //常量
                break;
            case IEnumerable<int> childSequence:  //声明模式 有类型转换 先is 后as进行类型转换
                {
                    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#中的模式匹配,更像语法糖,为什么这么说呢?下面我们一起看反编译工具还原的代码:

ublic static int SumPositiveNumbers(IEnumerable<object> sequence)
{
    int num;
    int num1 = 0;
    IEnumerator<object> enumerator = sequence.GetEnumerator();
    try
    {
        while (true)
        {
            if (enumerator.MoveNext())
            {
                object current = enumerator.get_Current();
                if (!(current is int)) //判断类型是否为int
                {
                    IEnumerable<int> enumerable = current as IEnumerable<int>;
                    if (enumerable != null)
                    {
                        IEnumerator<int> enumerator1 = enumerable.GetEnumerator();
                        try
                        {
                            while (enumerator1.MoveNext())
                            {
                                int current1 = enumerator1.get_Current();
                                num1 = num1 + (current1 > 0 ? current1 : 0);
                            }
                        }
                        finally
                        {
                            if (enumerator1 != null)
                            {
                                enumerator1.Dispose();
                            }
                        }
                    }
                    else
                    {
                        if (current == null) //判断为空
                        {
                            throw new NullReferenceException("Null found in sequence");
                        }
                        break;
                    }
                }
                else
                {
                    int num2 = (int)current; //直接进行类型强制转换
                    if (num2 != 0)
                    {
                        if (num2 > 0)
                        {
                            num1 += num2;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                num = num1;
                return num;
            }
        }
        throw new InvalidOperationException("Unrecognized type");  //default 最后处理
    }
    finally
    {
        if (enumerator != null)
        {
            enumerator.Dispose();
        }
    }
    num = num1;
    return num;
}

模式匹配增加,增强switch对类型的支持,从早期支持整数/枚举和字符串,到任意类型.

BenckmarkDotNet源码,是如何使用的:

internal static CoreRuntime FromVersion(Version version)
{
    switch (version)
    {
        case Version v when v.Major == 2 && v.Minor == 0: return Core20;
        case Version v when v.Major == 2 && v.Minor == 1: return Core21;
        case Version v when v.Major == 2 && v.Minor == 2: return Core22;
        case Version v when v.Major == 3 && v.Minor == 0: return Core30;
        case Version v when v.Major == 3 && v.Minor == 1: return Core31;
        case Version v when v.Major == 5 && v.Minor == 0: return GetPlatformSpecific(Core50);
        case Version v when v.Major == 6 && v.Minor == 0: return GetPlatformSpecific(Core60);
        case Version v when v.Major == 7 && v.Minor == 0: return GetPlatformSpecific(Core70);
        default:
            return CreateForNewVersion(#34;net{version.Major}.{version.Minor}", #34;.NET {version.Major}.{version.Minor}");
    }
}

BenchmarkDotNet现在是同步支持.Net版本,已经开始支持.Net 7,这和原先是不一样的,因为现在.Net 6已经发布rc1,最近应该发布rc2,下个月要发布正式版,在发布rc1时,代表.Net 6不会增加新的特性,并且新特性都会添加到.Net 7,.Net 7已经进入alpha了.

模式匹配 C# 8.0

在C# 8.0 模式匹配进一步得到了增强,这时候和rust的模式匹配使用很像.主要表现在:

  1. 增强switch表达式
  2. 增加属性模式
  3. 增加元祖模式
  4. 增加位置模式
public int PatternMatch8(int val) => val switch
{
    1 => 10,
    2 => 10 * 2,
    3 => 10 * 3,
    _ => 10 * 10,  //_代表弃元 在这里代替default
};

在使用ILSpy反编译工具:

C#模式匹配

c# 8.0的模式匹配只是语法糖

下面看一下属性模式:

/// <summary>
/// 属性模式
/// </summary>
/// <param name="people"></param>
/// <returns></returns>
public decimal PatternMatch8(People people) => people switch
{
    { Name: "tom" } => people.Salary * 1.1m,
    { Name: "jack" } => people.Salary * 1.2m,
    _ => 0m
};
C#模式匹配

c# 8.0属性模式编译后的代码

位置模式:

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);
}

看一下反编译代码:

C#模式匹配

c# 8 模式匹配之位置模式

看到位置模式,想到两个变量交换:

/// <summary>
/// 变量交换
/// </summary>
public void SwapVal()
{
    int a = 10, b = 20;
    System.Console.WriteLine(#34;a={a} b={b}");
    (a, b) = (b, a); //在c# 8.0,支持这样语法,以后看到这样的语法,不要蒙圈
    System.Console.WriteLine(#34;a={a} b={b}");
}
C#模式匹配

c# 8 增加新的语法,变量交换更简单

模式匹配 c# 9.0

public bool IsAlpha(char c)
{
    return c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';
}

反编译代码:

//dnspy反编译,这个更贴近IL
public bool IsAlpha(char c)
{
    if (c >= 'a')
    {
        if (c > 'z')
        {
            goto IL_1D;
        }
    }
    else
    {
        if (c < 'A')
        {
            goto IL_1D;
        }
        if (c > 'Z')
        {
            goto IL_1D;
        }
    }
    return true;
IL_1D:
    return false;
}
//ILSpy 反编译
public bool IsAlpha(char c)
{
    switch (c)
    {
        case 'A':
        case 'B':
        case 'C':
        case 'D':
        case 'E':
        case 'F':
        case 'G':
        case 'H':
        case 'I':
        case 'J':
        case 'K':
        case 'L':
        case 'M':
        case 'N':
        case 'O':
        case 'P':
        case 'Q':
        case 'R':
        case 'S':
        case 'T':
        case 'U':
        case 'V':
        case 'W':
        case 'X':
        case 'Y':
        case 'Z':
        case 'a':
        case 'b':
        case 'c':
        case 'd':
        case 'e':
        case 'f':
        case 'g':
        case 'h':
        case 'i':
        case 'j':
        case 'k':
        case 'l':
        case 'm':
        case 'n':
        case 'o':
        case 'p':
        case 'q':
        case 'r':
        case 's':
        case 't':
        case 'u':
        case 'v':
        case 'w':
        case 'x':
        case 'y':
        case 'z':
            return true;
        default:
            return false;
    }
}

这篇文章是国庆后就开始写的,一直没有完成(拖延症),年底了,开始对没有完成的博文进行清零.

龙芯LoongArch .Net编译组已经向.Net社区提交关于.Net 在LoongArch架构代码,在国产CPU个人跟看好LoongArch.尤其是看到Intel致信供应商禁用新疆产品新闻,希望我的下一台电脑是龙芯的,固态硬盘用致钛(长江存储).

个人能力有限,如果您发现有什么不对,请私信我

如果您觉得对您有用的话,可以点个赞或者加个关注,欢迎大家一起进行技术交流

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/13092.html

(0)
上一篇 2024-03-08 17:26
下一篇 2024-03-08 17:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信