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; }
类型参数T
受IMonoid<T>
接口约束,这使得该接口的静态虚拟成员Zero
和+
可以在T
itself 上被调用。
现在我们可以用一些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 文档以获取更多信息。
更多详情可查看官方公告。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
微软 DirectStorage 1.1 发布,正式推出 GPU 解压功能
微软的DirectStorage 是一项旨在让游戏充分利用高速存储(例如 NVMe SSD)的功能,它可以以最小的 CPU 开销,提供每秒数 GB 的小数据(例如 64kb)读取。目前 DirectStorage 1.1 已发布 ,这个版本正式带来了GPU 解压缩功能,在解压游戏资源方面加速了好几倍。 新东西: GPU 解压缩和 Gdeflate 压缩格式现已可用。 添加了 EnqueueSetEvent ,以使用 Win32 事件对象进行完成通知。 性能改进和错误修复。 GPU 解压缩功能 & Gdeflate 压缩格式 背景提要: 游戏需要大量数据来构建 —— 每个角色、物体和景观都有描述形状、光照和颜色等特征的“资产”,可能会增加数百 GB 的数据。 为了减少游戏的整体包大小,这些资产平时会被压缩。当游戏运行加载时,资产会被传输到系统内存中,CPU 负责解压缩数据,然后最终将其复制到 GPU 内存中,以供渲染需要时使用。 这些资产在游戏设备上的传输和解压极大地延长了游戏的加载时间,并限制了开放世界场景中包含的细节。 通常,解压缩的工作在 CPU 上完成,因为压缩格式历来仅...
- 下一篇
.NET 7 正式发布
微软宣布正式推出 .NET 7 ,使用 .NET 7 可以轻松地将 .NET 7 项目容器化,在 GitHub 操作中设置 CI/CD 工作流,并实现云原生可观察性。 .NET 7 是标准期限支持(STS) 版本,将支持 18 个月。在整个 .NET 7 版本中,超过 8900 名贡献者做出了 28k 代码贡献。 .NET 7 的优化主要集中在: 一个基类库(Base Class Library - BCL) 使用 .NET 7,只需学习一次,就可以通过一个 SDK、一个运行时、一组基础库重复构建多种类型的应用程序(云、Web、桌面、移动、游戏、IoT 和 AI)。 对 ARM64 的原生支持 优化了在 Arm 机器上的性能,包括估算 L3 缓存大小、引入了 LSE 原子指令、优化使用内在函数的库。 详情可查看 .NET 7 中的 Arm64 性能改进。 Linux 上增强的 .NET 支持 .NET 6 包含在 Ubuntu 22.04 (Jammy) 中,可以使用apt install dotnet6命令安装。此外,还有一个优化的、预构建的、开箱即用的超小型容器镜像。 dotn...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2配置默认Tomcat设置,开启更多高级功能