C# 11 预览版

C# 11 即将完成。这篇文章涵盖了 Visual Studio 17.3 中的新功能,和我们在 Visual Studio 17.2 的 4 月更新Visual Studio 17.1 的 2 月更新中未涵盖的功能。
此预览版中的新功能遵循 C# 11 的三个投资主题:

  • 对象初始化改进:无论您想对可变和不可变成员实施什么规则,您都可以更轻松地支持类型中的构造函数和对象初始值设定项。特点包括:

    • Required 成员
    • ref 字段
  • 通用数学支持:您可以为多种数字类型编写一次算法。这些功能使用 C# 和 .NET 进行统计、机器学习和其他数学密集型应用程序变得更加容易。特点包括:

    • 接口中的静态抽象和静态虚拟成员
    • 放宽右移要求
    • 无符号右移运算符
    • 数值IntPtr]
  • 开发人员生产力:我们添加了更多语言功能以提高您的工作效率。
    新的扩展特性:nameof

以下部分概述了 Microsoft Docs 中的每个功能和链接,您可以在其中阅读更多信息。要试用这些功能,您需要在您的项目中启用预览。文档中的 C# 11 中的新增功能一文对此进行了解释。

对象初始化改进

required成员允许您编写需要caller设置某些属性的类和结构类型。参考这个Person类型:

public class Person
{
    public string FirstName { get; init; }
    public string LastName {get; init; }
}

caller应该使用对象初始值设定项来设置 FirstName 和 LastName 属性的值。但在 Visual Studio 17.3 之前,编译器无法强制caller必须设置这些属性。需要参数的构造函数是确保用户设置FirstNameLastName属性的唯一方法。required成员需向编译器和caller传达他们必须设置这些属性。将required修饰符添加到成员声明中:

public class Person
{
    public required string FirstName { get; init; }
    public required string LastName {get; init; }
}

所有caller都必须包含FirstName和 LastName 属性的对象初始值设定项,否则编译器会发出错误提示。编译器通知caller 有required成员未初始化。开发人员必须立即解决这个问题。

如果 Person 类型是为早期版本编写的并且包含设置属性的构造函数,您仍然可以使用required成员。您应该使用 SetsRequiredMembers 属性标注任何现有的构造函数:

public class Person
{
    public required string FirstName { get; init; }
    public required string LastName {get; init; }

    [SetsRequiredMembers]
    public Person(string firstName, string lastName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }

    public Person() {}
}

SetsRequiredMembers 属性表示构造函数设置所有required成员。编译器知道使用

Person (string firstName, string lastName)

构造函数的调用者已经设置了required成员。无参数构造函数不包含该属性,因此使用该构造函数的调用者必须使用对象初始化器初始化所有required成员。

上面的示例使用了属性,但您也可以将required成员应用于字段声明。

此预览还包含 ref 字段和作用域值的初始实现。这些更改为 ref struct 类型中的 ref 字段提供了可用性。您还可以使用 scoped 关键词来限制 ref 参数的生命周期。功能提案和更新的更改现在提供了有关此功能的最佳文档。我们发现了一些需要更改语言才能安全使用的场景。更新的更改将在一个稍后发布的预览中提供,文档将反映最终设计。

通用数学支持

我们添加了通用数学作为激励场景的功能。您只会在高级场景中直接使用这些功能,例如编写适用于多种数字类型的数学算法。否则,您将间接受益,因为运行时使用了以下功能:

在接口中添加静态抽象和虚拟成员为通用数学打下了了许多重要的基础。该功能允许接口声明运算符以及其他静态方法。实现接口的类就像在接口中声明的其他方法一样必须提供静态抽象方法的实现。编译器在编译时解析对静态方法(包括运算符)的调用。没有像实例方法那样的运行时分派机制。该文档提供了有关使此功能正常工作所需的特定语言规则的更多详细信息。

其他语言特性消除了数字类型的一些差异,从而更容易编写通用数学算法。右移运算符不再要求第二个操作数是 int,而是 任何整数类型都可以!nint 和 nuint 类型分别是 System.IntPtr 和 System.UIntPtr 的同义词。这些关键字可以用来代替这些类型。事实上,新的分析器会提示您选择关键字而不是类型名称。最后,当您执行无符号移位时,无符号右移运算符 (>>>) 避免了强制转换。

综上所述,这些更改和检查运算符等其他更改支持通用数学运行时更改。语言改进意味着运行时团队可以对 .NET 中的所有数字类型进行改进。当您的类型使用运算符或其他静态方法实现合约时,您也可以利用这些功能。

开发人员生产力

nameof 运算符现在可以和方法参数一起使用。该功能允许您在方法的属性声明中使用 nameof 运算符,如下例所示:

[return:NotNullIfNotNull(nameof(url))]
string? GetTopLevelDomainFromFullUrl(string? url)

欢迎使用

请下载最新的 Visual Studio 2022 预览版并安装 .NET 7 预览版,您也可以单独安装 .NET 7 最新的预览版。安装后,您可以通过创建或打开 C# 项目并将 LangVersion 设置为 Preview 来尝试新的功能。

这个 Visual Studio 预览版让我们离 C# 11 的完整功能集更近了一步。我们在该版本中继续对多个主题进行投资。我们已经根据您给我们的反馈进行了修正。现在是下载预览版试用所有新功能并给我们提供反馈的好时机。我们正在关注 C# 11 和 .NET 7 并进行最终的更新。


了解更多 C# 11 中的新增功能,请前往官方文档。

你可能感兴趣的:(C# 11 预览版)