C# 8.0 中的新增功能( 三 )


可在此模式匹配高级教程中探索模式匹配方法 。
using 声明using 声明是前面带 using 关键字的变量声明 。它指示编译器声明的变量应在封闭范围的末尾进行处理 。以下面编写文本文件的代码为例:
C#
static int WriteLinesToFile(IEnumerable<string> lines){using var file = new System.IO.StreamWriter("WriteLines2.txt");// Notice how we declare skippedLines after the using statement.int skippedLines = 0;foreach (string line in lines){if (!line.Contains("Second")){file.WriteLine(line);}else{skippedLines++;}}// Notice how skippedLines is in scope here.return skippedLines;// file is disposed here}在前面的示例中,当到达方法的右括号时,将对该文件进行处理 。这是声明 file 的范围的末尾 。前面的代码相当于下面使用经典 using 语句的代码:
C#
static int WriteLinesToFile(IEnumerable<string> lines){// We must declare the variable outside of the using block// so that it is in scope to be returned.int skippedLines = 0;using (var file = new System.IO.StreamWriter("WriteLines2.txt")){foreach (string line in lines){if (!line.Contains("Second")){file.WriteLine(line);}else{skippedLines++;}}} // file is disposed herereturn skippedLines;}在前面的示例中,当到达与 using 语句关联的右括号时,将对该文件进行处理 。
在这两种情况下,编译器将生成对 Dispose() 的调用 。如果 using 语句中的表达式不可用,编译器将生成一个错误 。
静态本地函数现在可以向本地函数添加 static 修饰符,以确保本地函数不会从封闭范围捕获(引用)任何变量 。这样做会生成 CS8421,“静态本地函数不能包含对 <variable> 的引用 。”
考虑下列代码 。本地函数 LocalFunction 访问在封闭范围(方法 M)中声明的变量 y 。因此,不能用 static 修饰符来声明 LocalFunction:
C#
int M(){int y;LocalFunction();return y;void LocalFunction() => y = 0;}下面的代码包含一个静态本地函数 。它可以是静态的,因为它不访问封闭范围中的任何变量:
C#
int M(){int y = 5;int x = 7;return Add(x, y);static int Add(int left, int right) => left + right;}可处置的 ref 结构用 ref 修饰符声明的 struct 可能无法实现任何接口,因此无法实现 IDisposable 。因此,要能够处理 ref struct,它必须有一个可访问的 void Dispose() 方法 。此功能同样适用于 readonly ref struct 声明 。
可为空引用类型在可为空注释上下文中,引用类型的任何变量都被视为不可为空引用类型 。若要指示一个变量可能为 null,必须在类型名称后面附加 ?,以将该变量声明为可为空引用类型 。
对于不可为空引用类型,编译器使用流分析来确保在声明时将本地变量初始化为非 Null 值 。字段必须在构造过程中初始化 。如果没有通过调用任何可用的构造函数或通过初始化表达式来设置变量,编译器将生成警告 。此外,不能向不可为空引用类型分配一个可以为 Null 的值 。
不对可为空引用类型进行检查以确保它们没有被赋予 Null 值或初始化为 Null 。不过,编译器使用流分析来确保可为空引用类型的任何变量在被访问或分配给不可为空引用类型之前,都会对其 Null 性进行检查 。
可以在可为空引用类型的概述中了解该功能的更多信息 。可以在此可为空引用类型教程中的新应用程序中自行尝试 。在迁移应用程序以使用可为空引用类型教程中了解迁移现有代码库以使用可为空引用类型的步骤 。
异步流从 C# 8.0 开始,可以创建并以异步方式使用流 。返回异步流的方法有三个属性:

  1. 它是用 async 修饰符声明的 。
  2. 它将返回 IAsyncEnumerable<T> 。
  3. 该方法包含用于在异步流中返回连续元素的 yield return 语句 。
使用异步流需要在枚举流元素时在 foreach 关键字前面添加 await 关键字 。添加 await 关键字需要枚举异步流的方法,以使用 async 修饰符进行声明并返回 async 方法允许的类型 。通常这意味着返回 Task 或 Task<TResult> 。也可以为 ValueTask 或 ValueTask<TResult> 。方法既可以使用异步流,也可以生成异步流,这意味着它将返回 IAsyncEnumerable<T> 。下面的代码生成一个从 0 到 19 的序列,在生成每个数字之间等待 100 毫秒:
C#
public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence(){for (int i = 0; i < 20; i++){await Task.Delay(100);yield return i;}}可以使用 await foreach 语句来枚举序列:
C#
await foreach (var number in GenerateSequence()){Console.WriteLine(number);}


推荐阅读