VS 2019要來了,是時候瞭解一下C# 8.0新功能

近日,微軟發佈了Visual Studio 2019 的發佈日期,2019年4月2日Visual Studio 2019 將正式和大家見面,同時微軟還將提供發佈現場實時直播。

除了Visual Studio 2019自身之外,VS 2019的發佈還牽動着很多C#開發者的心。雖然一個月之前發佈的Visual Studio 2019 Preview版本已經可以試用C#的某些新功能,但還有一些是不可試用的。

下面我們就來看一下微軟官方對C#8.0重要功能的概述。

可空的引用類型

此功能的目的是防止無處不在的空引用異常,空引用異常已經困擾面向對象編程半個世紀了。該功能將阻止開放者將null值放入到普通的引用類型中,例如String類型不可爲空。但它不是強制性的error,而是比較溫和的warning。

這些異常現在已經過了半個世紀的面向對象編程。
它阻止你null進入普通的引用類型,例如string- 它使這些類型不可爲空!它是溫和的,有警告,而不是錯誤。但是在現有代碼上會出現新警告,因此您必須選擇使用該功能(您可以在項目,文件甚至源代碼級別執行此功能)。
string s = null; // Warning: Assignment of null to non-nullable reference type
如果你想要使用null怎麼?可以使用空的引用類型,例如string?:
string? s = null; // Ok
當你使用了可空引用時,需要先檢查一下其是否爲null,編譯器會分析代碼流,以查看null值是否可以將其用於您使用它的位置:

void M(string? s)
{
    Console.WriteLine(s.Length); // Warning: Possible null reference exception
    if (s != null)
    {
        Console.WriteLine(s.Length); // Ok: You won't get here if s is null
    }
}

C#允許表達可空的意圖,但是在不遵守規則時會發出警告。

異步流

C#5.0的async / await功能允許在簡單的代碼中使用(並生成)異步結果,而無需回調:

async Task<int> GetBigResultAsync()
{
    var result = await GetResultAsync();
    if (result > 20) return result; 
    else return -1;
}

下面我們來介紹一下大家期待已久的IAsyncEnumerable, 異步版本的IEnumerable。該語言允許await foreach使用元素,並使用yield return生成元素。

async IAsyncEnumerable<int> GetBigResultsAsync()
{
    await foreach (var result in GetResultsAsync())
    {
        if (result > 20) yield return result; 
    }
}

範圍和索引

我們正在添加一個可用於索引的Index類型。你可以使用int從頭創建,也可以使用^從末尾開始計算前綴運算符:
Index i1 = 3; // number 3 from beginning
Index i2 = ^4; // number 4 from end
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // “3, 6”
另外,我們還引入了一個Range類型,它由兩個Indexes 組成,一個用於開始,一個用於結束,並且可以用x…y 範圍表達式編寫。
可以使用a進行索引Range以生成切片:
var slice = a[i1…i2]; // { 3, 4, 5 }

接口成員的默認實現

今天,大家對於界面都有這樣一個需求:在不破壞現有狀態的情況下添加一個成員。

在C#8.0中,我們會爲接口成員提供一個主體。如果有人沒有實現該成員(或者是在編寫代碼時還沒有實現),會獲得默認實現。

interface ILogger
{
    void Log(LogLevel level, string message);
    void Log(Exception ex) => Log(LogLevel.Error, ex.ToString()); // New overload
}

class ConsoleLogger : ILogger
{
    public void Log(LogLevel level, string message) { ... }
    // Log(Exception) gets default implementation
}

在ConsoleLogger類不需要實現ILogger的Log(Exception)重載,因爲它已經默認實現了。現在只要給當前實現者提供了默認實現,就可以向現有公共接口添加新成員。

遞歸模式

我們允許pattern中包含其他pattern:

IEnumerable<string> GetEnrollees()
{
    foreach (var p in People)
    {
        if (p is Student { Graduated: false, Name: string name }) yield return name;
    }
}

pattern Student { Graduated: false, Name: string name }主要檢查Person是a Student,然後將常量pattern false應用於其Graduated屬性以查看它們是否仍然已註冊,並將pattern string name應用於其Name屬性以獲取其名稱(如果爲非null)。因此,如果p是一個Student,尚未畢業並且姓名非空,那麼我們就可以yield return這個名字。

Switch表達式

帶有pattern的switch語句在C#7.0中已經非常強大了,但是編寫起來卻很麻煩,而Switch 表達式卻是一個解決這種問題的、“輕量級”的版本。

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

目標類型的新表達式

在許多情況下,往往創建新對象時,類型已經從上下文中給出。在這些情況下,我們會讓你省略類型:
Point[] ps = { new (1, 4), new (3,-2), new (9, 5) }; // all Points

C#大版本關鍵更新回顧

C#1.0(Visual Studio .NET)

  • Classes
  • Structs
  • Interfaces
  • Events
  • Properties
  • Delegates
  • Expressions
  • Statements
  • Attributes
  • Literal

C#2(VS 2005)

  • Generics
  • Partial types
  • Anonymous methods
  • Iterators
  • Nullable types
  • Getter/setter separate accessibility
  • Method group conversions (delegates)
  • Static classes
  • Delegate inferenc

C#3(VS 2008)

  • Implicitly typed local variables
  • Object and collection initializers
  • Auto-Implemented properties
  • Anonymous types
  • Extension methods
  • Query expressions
  • Lambda expression
  • Expression trees
  • Partial methods

C#4(VS 2010)

  • Dynamic binding
  • Named and optional arguments
  • Co- and Contra-variance for generic delegates and interfaces
  • Embedded interop types (“NoPIA”

C#5(VS 2012)

  • Asynchronous methods
  • Caller info attributes

C#6(VS 2015)

  • Draft Specification online
  • Compiler-as-a-service (Roslyn)
  • Import of static type members into namespace
  • Exception filters
  • Await in catch/finally blocks
  • Auto property initializers
  • Default values for getter-only properties
  • Expression-bodied members
  • Null propagator (null-conditional operator, succinct null checking)
  • String interpolation
  • nameof operator
  • Dictionary initializer

C#7.0(Visual Studio 2017)

平臺依賴

大多數的C# 8.0功能都可以在任何版本的.NET上運行,但也有一些功能是有平臺依賴性的,例如異步流、範圍和索引都依賴 .NET Standard 2.1一部分的新框架類型。其中,.NET Standard 2.1、.NET Core 3.0以及Xamarin,Unity和Mono都將實現 .NET Standard 2.1,而.NET Framework 4.8不會,所以如果你使用的是 .NET Framework 4.8,那麼C# 8.0的部分功能可能不能使用。

另外,接口成員的默認實現也依賴新的運行時增強功能,所以此功能也不適用於 .NET Framework 4.8和舊版本的 .NET。

微軟官方博客鏈接:https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章