C#(99):C# 8.0 新特性( NET Framework 4.8 、 .NET Core 3.x、.NET Standard 2.1和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;
     }
 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM