• C#(99):C# 8.0 的新特性( NET Framework 4.8 与 Visual Studio 2019 )


     C#8.0 于 2019年4月 随 .NET Framework 4.8 与 Visual Studio 2019 一同发布

    使用VS2019体检C#8.0新功能:

    编辑.csproj文件,添加如下代码

    <PropertyGroup>
      <LangVersion>preview</LangVersion>
     </PropertyGroup>

    一、可空引用类型(Nullable reference types)

    引用类型将会区分是否可空,可以从根源上解决 NullReferenceException。

    #nullable enable
            void M(string? s)
            {
                Console.WriteLine(s.Length); // 产生警告:可能为 null
                if (s != null)
                {
                    Console.WriteLine(s.Length); // Ok
                }
            }
    #nullable disable

    二、异步流(Async streams)

    考虑到大部分 Api 以及函数实现都有了对应的 async版本,而 IEnumerable<T>和 IEnumerator<T>还不能方便的使用 async/await就显得很麻烦了。
      但是,现在引入了异步流,这些问题得到了解决。
      我们通过新的 IAsyncEnumerable<T>和 IAsyncEnumerator<T>来实现这一点。同时,由于之前 foreach是基于IEnumerable<T>和 IEnumerator<T>实现的,因此引入了新的语法await foreach来扩展 foreach的适用性。

    async Task<int> GetBigResultAsync()
    {
        var result = await GetResultAsync();
        if (result > 20) return result; 
        else return -1;
    }
    
    async IAsyncEnumerable<int> GetBigResultsAsync()
    {
        await foreach (var result in GetResultsAsync())
        {
            if (result > 20) yield return result; 
        }
    }

    三、范围和下标类型(Ranges and indices)

    C# 8.0 引入了 Index 类型,可用作数组下标,并且使用 ^ 操作符表示倒数。
      不过要注意的是,倒数是从 1 开始的。

    Index i1 = 3;  // 下标为 3
    Index i2 = ^4; // 倒数第 4 个元素
    int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"



    除此之外,还引入了 “..” 操作符用来表示范围(注意是左闭右开区间)。

    var slice = a[i1..i2]; // { 3, 4, 5 }

    关于这个下标从 0 开始,倒数从 1 开始,范围左闭右开。

    四、模式匹配表达式(Switch expressions )

    典型的模式匹配语句,只不过没有用“match”关键字,而是沿用了了“switch”关键字

    object figure = "";
    var area = figure switch
    {
        Line _ => 0,
        Rectangle r => r.Width * r.Height,
        Circle c => c.Radius * 2.0 * Math.PI,
        _ => throw new UnknownFigureException(figure)
    };

    C# 8.0中的模式匹配相对C# 7.0来说有了进一步的增强,对于如下类:

    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# 7.0中一个经典的模式匹配示例:

    static string Display(object o)
    {
        switch (o)
        {
            case Point p when p.X == 0 && p.Y == 0:
                return "origin";
            case Point p:
                return $"({p.X}, {p.Y})";
            default:
                return "unknown";
        }
    }

    在C# 8.0中,它有更加精简的写法。

    1、Switch表达式

    在C# 8.0中,可以利用新的switch方式成模式匹配:

    static string Display(object o) => o switch
    {
        Point p when p.X == 0 && p.Y == 0 => "origin",
        Point p                           => $"({p.X}, {p.Y})",
        _                                 => "unknown"
    };

    它利用一条switch语句完成了模式匹配,第一样看上去要简洁一些。不过,它还有更多更简单的写法。

    2、Property patterns

    可以直接通过在属性上指定值作为判定条件,

    static string Display(object o) => o switch
    {
        Point { X: 0, Y: 0 } => "origin",
        Point p              => $"({p.X}, {p.Y})",
        _                    => "unknown"
    };

    也可以将属性值传递出来。

    static string Display(object o) => o switch
    {
        Point { X: 0, Y: 0 }         => "origin",
        Point { X: var x, Y: var y } => $"({x}, {y})",
        _                            => "unknown"
    };

    3、Positional patterns

    利用解构函数,可以写出更加精简的表达式。

    static string Display(object o) => o switch
    {
        Point(0, 0)         => "origin",
        Point(var x, var y) => $"({x}, {y})",
        _                   => "unknown"
    };

    如果没有类型转换,则可以写得更加简单了:

    static string Display(Point o) => o switch
    {
        (0, 0)         => "origin",
        (var x, var y) => $"({x}, {y})"
    };

    4、非空判断

    如果只是判断空和非空,则有最简单的模式:

    { }  => o.ToString(),
    null => "null"

    5、Tuple patterns

    也支持直接对ValueTuple进行模式匹配,用起来非常灵活。

    static State ChangeState(State current, Transition transition, bool hasKey) =>
        (current, transition, hasKey) switch
    {
        (Opened, Close, _)     => Closed,
        (Closed, Open,  _)     => Opened,
        (Closed, Lock, true)   => Locked,
        (Locked, Unlock, true) => Closed,
        _ => throw new InvalidOperationException($"Invalid transition")
    };

    五、递归模式语句(recursive patterns)

    现在可以这么写了(patterns 里可以包含 patterns)

    IEnumerable<string> GetEnrollees()
    {
        foreach (var p in People)
        {
            if (p is Student { Graduated: false, Name: string name }) yield return name;
         }
     }
  • 相关阅读:
    清除页面广告?身为前端,自己做一款简易的Chrome扩展吧
    Nginx 引入线程池,提升 9 倍性能
    调试时屏蔽JavaScript库代码 –Chrome DevTools Blackbox功能介绍
    收集的React.JS资料
    谈谈 React.js 的核心入门知识
    同时包含字母和数字的正则表达式
    Word2010撤销按钮失效,Ctrl+Z失效解决办法
    大数据于产业金融领域的运用究竟如何很好的实现
    HTTP 错误 500.19
    WindowsServer2012桌面图标设置
  • 原文地址:https://www.cnblogs.com/springsnow/p/11046251.html
Copyright © 2020-2023  润新知