C# 11 正式发布


C# 11 现已发布。公告称,“随着每个版本的发布,社区的参与度越来越高,贡献了从建议、见解和错误报告到整个功能实现的所有内容。这真的是每个人的 C#。”

新版本中的一些亮点更新内容包括:

UTF-8 字符串(UTF-8 String Literals)

默认情况下,C# 字符串被硬编码为 UTF-16,而 Internet 上通行的字符串编码是 UTF-8。为了最大限度地减少转换的麻烦和性能开销,现在可以简单地为你的 string literals 附加一个u8后缀,以便立即将它们转换为 UTF-8:

var u8 = "This is a UTF-8 string!"u8;

UTF-8 string literals 只是给你返回一个字节块——以ReadOnlySpan<byte>形式。对于那些需要 UTF-8 编码的场景,这可能比一些专门的新的 UTF-8 字符串类型更有用。

阅读有关UTF-8 字符串文字的文档。

原始字符串 (Raw string literals)

从 C# 11 开始,可以使用原始字符串字面量更轻松地创建多行字符串,或使用需要转义序列的任何字符。 原始字符串字面量无需使用转义序列。 你可以编写字符串,包括空格格式,以及你希望在输出中显示该字符串的方式。 原始字符串字面量:

  • 以至少三个双引号字符序列 (""") 开头和结尾。 可以使用三个以上的连续字符开始和结束序列,以支持包含三个(或更多)重复引号字符的字符串字面量。
  • 单行原始字符串字面量需要左引号和右引号字符位于同一行上。
  • 多行原始字符串字面量需要左引号和右引号字符位于各自的行上。
  • 在多行原始字符串字面量中,会删除右引号左侧的任何空格。

Raw string literals 由至少三个双引号分隔:

var raw1 = """This\is\all "content"!""";
Console.WriteLine(raw1);

This prints:

This\is\all "content"!

如果你需要三个或更多的"s 成为你内容的一部分,只需在外部使用更多的"s。开头和结尾必须一致。

var raw2 = """""I can do ", "", """ or even """" double quotes!""""";

这使得粘贴、维护和一目了然地阅读文字所包含的内容变得非常容易。

多行 raw string literals 也可以截断前导空格:末端引号的位置决定了空格开始包含在输出中的位置:

var raw3 = """
<element attr="content">
<body>
This line is indented by 4 spaces.
</body>
</element>
""";
//^white space left of here is removed

由于末端引号的左侧有四个空格,因此将从每行内容的开头删除四个空格,从而产生以下输出:

<element attr="content">
<body>
This line is indented by 4 spaces.
</body>
</element>

此外,Raw string literals 支持插值,可在文档中阅读有关的更多信息。

对静态成员进行抽象

在 C# 11 中发布了对接口中静态虚拟成员的支持,此功能在 C# 10 中处于预览状态。有了它,你现在可以定义一个非常简单的数学接口:

public interface IMonoid<TSelf> where TSelf : IMonoid<TSelf>
{
public static abstract TSelf operator +(TSelf a, TSelf b);
public static abstract TSelf Zero { get; }
}

任何人现在都可以通过为两个静态成员提供实现并将自己作为TSelf类型参数传递来实现此接口:

public struct MyInt : IMonoid<MyInt>
{
int value;
public MyInt(int i) => value = i;
public static MyInt operator +(MyInt a, MyInt b) => new MyInt(a.value + b.value);
public static MyInt Zero => new MyInt(0);
}

重要的是,你如何使用这些抽象的操作?当没有实例可供调用时,你如何调用虚拟成员?答案是通过泛型:

T AddAll<T>(params T[] elements) where T : IMonoid<T>
{
T result = T.Zero;
foreach (var element in elements)
{
result += element;
}
return result;
}

类型参数TIMonoid<T>接口约束,这使得该接口的静态虚拟成员Zero+可以在Titself 上被调用。

现在我们可以用一些MyInt来调用泛型方法,而+Zero的正确实现则通过类型参数传递进来:

MyInt sum = AddAll<MyInt>(new MyInt(3), new MyInt(4), new MyInt(5));

事实上,.NET 7提供了一个新的命名空间System.Numerics,其中充满了数学接口,代表了不同的运算符组合和其他你想使用的静态成员:上述小IMonoid<T>接口的"grown-up"版本。.NET中的所有数字类型现在都实现了这些新的接口--你也可以为你自己的类型添加这些接口。

还值得注意的是,静态虚拟成员对数学以外的其他事物也很有用。更多详情可在有关静态抽象接口方法和通用数学的文档中查看。即使你不使用静态虚拟成员创建接口,也可以从他们现在和将来对 .NET 库所做的改进中受益。

列表模式(List patterns)

Pattern matching 是在 C# 7 中引入的,从那时起它已发展成为该语言中最重要和最强大的控制结构之一;C# 11 添加了列表模式从 C# 11 开始,可以将数组或列表与模式的序列进行匹配,如以下示例所示:

int[] numbers = { 1, 2, 3 };

Console.WriteLine(numbers is [1, 2, 3]);// True
Console.WriteLine(numbers is [1, 2, 4]);// False
Console.WriteLine(numbers is [1, 2, 3, 4]);// False
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]);// True

如前面的示例所示,当每个嵌套模式与输入序列的相应元素匹配时,列表模式就会匹配。 可使用列表模式中的任何模式。 若要匹配任何元素,请使用弃元模式,或者,如果还想捕获元素,请使用 var 模式,如以下示例所示:

List<int> numbers = new() { 1, 2, 3 };

if (numbers is [var first, _, _])
{
Console.WriteLine($"The first element of a three-item list is {first}.");
}
// Output:
// The first element of a three-item list is 1.

前面的示例将整个输入序列与列表模式匹配。 若要仅匹配输入序列开头或/和结尾的元素,请使用列表模式中的切片模式..,如以下示例所示:

Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]);// True
Console.WriteLine(new[] { 1, 1 } is [_, _, ..]);// True
Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]);// False
Console.WriteLine(new[] { 1 } is [1, 2, ..]);// False

Console.WriteLine(new[] { 1, 2, 3, 4 } is [.., > 0, > 0]);// True
Console.WriteLine(new[] { 2, 4 } is [.., > 0, 2, 4]);// False
Console.WriteLine(new[] { 2, 4 } is [.., 2, 4]);// True

Console.WriteLine(new[] { 1, 2, 3, 4 } is [>= 0, .., 2 or 4]);// True
Console.WriteLine(new[] { 1, 0, 0, 1 } is [1, 0, .., 0, 1]);// True
Console.WriteLine(new[] { 1, 0, 1 } is [1, 0, .., 0, 1]);// False

切片模式匹配零个或多个元素。 最多可在列表模式中使用一个切片模式。

还可以在切片模式中嵌套子模式,如以下示例所示:

void MatchMessage(string message)
{
var result = message is ['a' or 'A', .. var s, 'a' or 'A']
? $"Message {message} matches; inner part is {s}."
: $"Message {message} doesn't match.";
Console.WriteLine(result);
}

MatchMessage("aBBA");// output: Message aBBA matches; inner part is BB.
MatchMessage("apron");// output: Message apron doesn't match.

void Validate(int[] numbers)
{
var result = numbers is [< 0, .. { Length: 2 or 4 }, > 0] ? "valid" : "not valid";
Console.WriteLine(result);
}

Validate(new[] { -1, 0, 1 });// output: not valid
Validate(new[] { -1, 0, 0, 1 });// output: valid

更多详情可查看相关文档。

Required members

 

开发团队已经在多个版本中进行了改进对象的创建和初始化的工作,C# 11 则通过 required members 来继续这些改进。

在创建使用对象初始化器的类型时,曾经无法指定必须初始化某些属性。现在,可以说一个属性或字段是required。这意味着,当创建该类型的对象时,它必须被对象初始化器初始化:

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

现在在不初始化两个必需属性的情况下创建一个Person是错误的:

var person = new Person { FirstName = "Ada" }; // Error: no LastName!

查看 required members 文档以获取更多信息。

更多详情可查看官方公告。


相關推薦

2023-10-08

经过 4 个多月的测试和打磨,微软近日宣布 C# Dev Kit 正式 GA。 微软表示在预览版期间,累计为 C# Dev Kit 修复了 350 多个问题,其中大部分由社区报告,并对该产品进行了 300 多项有针对性的改进。 微软称用户的反馈加速

2022-02-28

.NET 首席项目经理凯瑟琳在博客中介绍了 C# 11 的一些预览性新功能,这些功能可以在 Visual Studio 17.1 和 .NET SDK 6.0.200 中体验,下面摘录一部分新特性作介绍: C# 11 预览:允许在内插字符串的“插值表达式”中换行 内插

2023-08-05

ILSpy 是一个开源的 .NET 反编译工具。ILSpy 8.0 现已发布,与前几代基于 .NET Framework 4.7.2 的 ILSpy 相比,ILSpy 8 基于 .NET 6.0。除独立分发版之外的所有工件都依赖于框架构建,这意味着必须在启动 ILSpy 之前安装 .NET 6.0.2。 具

2023-10-10

TIOBE 公布了 2023 年 10 月的编程语言排行榜。 C# 和 Java 之间的差距越来越小,达到了历史新低,目前两者的差距仅为 1.2%。TIOBE CEO Paul Jansen 认为,如果这一趋势继续保持,那么 C# 将在两个月后超过 Java。 在所有编

2023-11-29

  帮助文档: https://gitee.com/yhuse/SunnyUI/wikis/pages Gitee: https://gitee.com/yhuse/SunnyUI GitHub: https://github.com/yhuse/SunnyUI Nuget: https://www.nuget.org/packages/SunnyUI/ Blog: https://www.cnblogs.com/yhuse SunnyUI.Net 是基于.Net F

2023-11-23

  帮助文档: https://gitee.com/yhuse/SunnyUI/wikis/pages Gitee: https://gitee.com/yhuse/SunnyUI GitHub: https://github.com/yhuse/SunnyUI Nuget: https://www.nuget.org/packages/SunnyUI/ Blog: https://www.cnblogs.com/yhuse SunnyUI.Net 是基于.Net F

2023-02-22

Visual Studio 2022 17.5 正式发布,新版本带来了诸如多合一搜索、基于 AI 和用户意图的建议、改进的 Dev Tunnels 等一系列新功能和改进。 下载:https://visualstudio.microsoft.com/downloads/ 生产力 多合一搜索 基于意图和 AI 的建议 调试

2022-12-14

p, laravel, wordpress. 6、C/C++ 自 C 语言的首次发布至今已有 50 年的历史,从后来 C++ 的诞生到现在也已经过去了 37 年,C++ 最初的名字是 "C with Classes"。在这个漫长的时间窗口中,C/C++ 通过对语言的定期补充和改进保

2023-06-08

Dev Kit 扩展后将把 C# 扩展升级到与 C# Dev Kit 兼容的最新预发布版本。 C# Dev Kit 的一些功能建立在与 Visual Studio 相同的基础上,因此它使用与 Visual Studio 相同的许可模式 —— C# Dev Kit 对个人、学术研究和开源开发是免费的,与 Vis

2022-06-17

6 月 16 日,微软项目经理 Tim Heuer 公布了 VSCode C# 扩展的路线图更新,新的路线图引入语言服务器协议(LSP) 作为 VSCode C# 扩展的基础通信机制,并计划创建一个新的“LSP Tools Host”组件作为新版 C# 扩展的基础,以引入更多

2022-10-10

  帮助文档: https://gitee.com/yhuse/SunnyUI/wikis/pages Gitee: https://gitee.com/yhuse/SunnyUI GitHub: https://github.com/yhuse/SunnyUI Nuget: https://www.nuget.org/packages/SunnyUI/ Blog: https://www.cnblogs.com/yhuse SunnyUI.Net 是基于

2023-02-11

微软在 .NET 平台上提供了对 3 种编程语言的支持 —— C#、F# 和 Visual Basic。近日它公布了针对每种语言的最新支持策略。总的来说,微软依然致力于全面支持上述三种编程语言,重点是 C# 和 F#,他们会优化这两门语言的向后兼容

2023-07-19

  帮助文档: https://gitee.com/yhuse/SunnyUI/wikis/pages Gitee: https://gitee.com/yhuse/SunnyUI GitHub: https://github.com/yhuse/SunnyUI Nuget: https://www.nuget.org/packages/SunnyUI/ Blog: https://www.cnblogs.com/yhuse SunnyUI.Net 是基于

2021-11-09

微软宣布 .NET 6 已正式推出,并称其为迄今为止最快的 .NET 版本。 发布公告提到,.NET 6 是首个原生支持 Apple Silicon (Arm64) 的版本,并且还针对 Windows Arm64 进行了改进。.NET 团队构建了一个新的动态配置文件引导优化 (PGO