微軟計畫 C# 8.0 與 .NET Core 3.0 同一時間發布,應該是跟隨 Visual Studio 2019 一起上線吧。

Nullable reference types

本來的可空類型是經由 System.Nullable where T : struct 來實作,所以只有 struct 類型才可以使用,如

1
2
int? a = null;
string? s = null; // 編譯錯誤

而現在連 reference types 也可以當作可空類型,如

1
2
3
4
5
void Method (string? s) {
if (s != null) {
Console.WriteLine(s.Length); //不為 null 才能使用成員
}
}

可以取代空字串的使用。

小提一下個人理解,null 是不指向任何值;string.Empty 是指向一個 String 的靜態屬性;”” 是建立一個字串並給予空值。

而這邊有個問題,不知道是哪邊出問題 string s = null 並不會像官方範例一樣跳出警告。

Async streams

IAsyncEnumerable 為 IEnumerable 的非同步版本,如

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

等正式上線再來實作看看。

Ranges and indices

新的類型 Index,可以用於集合的查找上,如

1
2
3
4
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"

也可以當作範圍使用,如

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

Default implementations of interface members

介面成員增加預設實作的成員。

改善介面發布後,若介面有新增成員,實作該介面的類別不再強制需要補寫新成員,有一個預設實作成員,如果需要改變才另寫實作。

1
2
3
4
5
6
7
8
9
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
}

Recursive patterns

允許新寫法如

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

個人猜類似於

1
2
3
4
5
IEnumerable<string> GetEnrollees () {
foreach (var p in People) {
if (p is Student && p.Graduated == false && p.Name is string) yield return p.name;
}
}

Switch expressions

Switch 的表達式

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

個人猜類似於以下陳述式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var area = 0;
switch (figure) {
case Line _:
area = 0;
break;
case Rectangle r:
area = r.Width * r.Height;
break;
case Circle c:
area = Math.PI * c.Radius * c.Radius;
break;
default:
throw new UnknownFigureException (figure);
break;
}

switch 的陳述式更新可以參考
C# 7.0 的新功能 - C# 指南 | Microsoft Docs

Target-typed new-expressions

當上下文可以推導出類型時,可以省略類型。

1
Point[] ps = { new (1, 4), new (3,-2), new (9, 5)};

個人猜類似於

1
Point[] ps = { new Point (1, 4), new Point (3,-2), new Point (9, 5)};

總結

官方的文章還有提到平台的依賴,但應該不用特別注意,大多數的平台都可以運行,除了 .NET Framework 4.8 版本不能使用 Async streams 與 Default interface member implementations 特性。

雖然我記得還有一些新特性,但可能不是官方正式文件所以不在這次的改版內容裡。

參考資料

Building C# 8.0 | .NET Blog

C# - 維基百科,自由的百科全書

Nullable<T> Struct (System) | Microsoft Docs