C# 13 中的新增功能实操

笔记哥 / 03-29 / 25点赞 / 0评论 / 226阅读
## 前言 今天大姚带领大家一起来看看 C# 13 中的新增几大功能,并了解其功能特性和实际应用场景。 ## 前提准备 要体验 C# 13 新增的功能可以使用最新的 Visual Studio 2022 版本或 .NET 9 SDK 尝试这些功能。 ### Visual Studio 2022安装 - ![](https://cdn.res.knowhub.vip/c/2503/29/73b62393?GzMAAET1PK%2fp7%2fuEyHYw0Xq0Ir7kg5TM0jVdOqxAXGFRb0SWFf0mc2qLX9%2fN2yYwCA%3d%3d) ![](https://cdn.res.knowhub.vip/c/2503/29/e34479be.png?G1cAAMTsdJxI8iGl26hD2jvFHc2ARRpBpYT1es9Z%2byb6fgcjxWe0Pn1%2f%2bE3r00lUTWolMDIrQkCBqIJhHERLuqQY57iGAw%3d%3d) ### .NET 9 SDK - ![](https://cdn.res.knowhub.vip/c/2503/29/ad571514.0?GzUAAMTsFpO9SqvDTbA5%2b6QLEcUWqKSVrZuRNzswgj4pZ%2buLjMUh%2fnwr6ojgRJMK) ![](https://cdn.res.knowhub.vip/c/2503/29/b25570c2.png?G1YAAETn9LwUC2DGvtMdbIlTE20GJLIIKiWs13vO2jfR9wcX1vyM1mfsD39pfQZBpMKduLAVQfJ8MUTV3JAUEHVxy2sE) ## params 集合 在 C# 13 中,params 的改进使其从可变数量的数组参数升级为可变数量的集合类型参数。这一改进通过支持高性能集合类型(如`Span、ReadOnlySpan`)和简化调用语法,显著提升了代码的灵活性和效率。 > > > C# 13 中的 params 集合变得类型更灵活,满足更复杂的应用场景,并且性能得到了进一步的提升。 > ### 在 C# 13 之前: params 仅支持一维数组(如`params int[] list`、`params object[] list`)。调用方法时需显式传递数组或数组元素类型的参数的逗号分隔列表。 ### 在 C# 13 中: params 修饰符并不局限于数组类型。 现在可以将 params 用于任何已识别的集合类型,包括 `System.Span、System.ReadOnlySpan`,以及那些实现 `System.Collections.Generic.IEnumerable` 并具有 Add 方法的类型。 除了具体类型外,还可以使用接口 `System.Collections.Generic.IEnumerable、System.Collections.Generic.IReadOnlyCollection、System.Collections.Generic.IReadOnlyList、System.Collections.Generic.ICollection和 System.Collections.Generic.IList`。 ```csharp public static void SpanDataPrintRun() { Span originalSpan = [1, 2, 3, 4, 5]; SpanDataPrint(originalSpan); } public static void SpanDataPrint(params Span spans) { for (int i = 0; i < spans.Length; i++) { Console.WriteLine(spans[i]); } } ``` ## 新增Lock锁对象 .NET 9 包含一种新的用于互斥的 `System.Threading.Lock` 类型,比仅在任意 `System.Object` 实例上进行锁定更有效。该类型通过其 API 提供更好的线程同步,通过`Lock.EnterScope()`返回的`ref struct`自动管理锁的释放,减少死锁风险。 - System.Threading.Lock类型提案:![](https://cdn.res.knowhub.vip/c/2503/29/b3a0bc3b?Gy0AAMTcRjEePkFsURxuwQd3K42QijWUfN6BZdQYBr%2fMyyPEj0PbAnMPcZTaUgY%3d) ![](https://cdn.res.knowhub.vip/c/2503/29/ac8135a2.png?G1cAAMTsdJxI8qGk26hD2jvFHc2ARRpBpYT1es9Z%2byb6fgcjxWe0Pn1%2f%2bE3r00lULzEjMDIrQkCFaIbmYgGcCmotJnENBw%3d%3d) ```csharp         private object _oldLock = new object();         private System.Threading.Lock _newLock = new System.Threading.Lock();         public void LockTest()         {             lock (_oldLock)             {                 Console.WriteLine("Old lock");             }             lock (_newLock)             {                 // 传统 lock 语法(优化版)             }             using (_newLock.EnterScope())             {                 //  作用域自动释放(推荐写法)             }             _newLock.Enter();             try             {                 // 显式 Enter/Exit 调用             }             finally { _newLock.Exit(); }             if (_newLock.TryEnter())             {                 try                 {                     // 非阻塞尝试获取锁                 }                 finally { _newLock.Exit(); }             }         } ``` ## 新的转义序列 新增 `\e` 转义字符作为 `ESCAPE` 字符 `Unicode U+001B` 的字符文本转义序列。以前,只能使用的是 `\u001b` 或 `\x1b`。不建议使用`\x1b`,因为如果 `1b` 后面的下一个字符是有效的十六进制数字,则那些字符会成为转义序列的一部分。 ```csharp public static void NewEscapeSequence() { Console.WriteLine("[31m红色文本[0m"); // C# 13 之前 Console.WriteLine("\u001b[31m红色文本\u001b[0m"); //输出红色文字 // C# 13 中 Console.WriteLine("\e[31m红色文本\e[0m");//功能相同,语法更简洁 } ``` ![](https://cdn.res.knowhub.vip/c/2503/29/62205bc9.png?G1YAAMTsdJxIPgml26hD2jvFHc2ARBZBpYT1es9Z%2byb6fhcWi89offr%2b8JfWpxNUM2olYUmsCF6KQDOKmQWFXYCmGtdw) ## 方法组自然类型改进 此功能对涉及方法组的重载解析进行了少量优化。方法组是一个方法,并且所有重载都具有相同的名称。 编译器以前的行为是为方法组构造完整的候选方法集。如果需要自然类型,则自然类型是根据整套候选方法确定的。 - 详细介绍:![](https://cdn.res.knowhub.vip/c/2503/29/a7e4a1ce?G34AAORNd17Ooq%2fvG85wMFWmBOUYJ2Ajns8yLcPGw0ROrIO2TlIVeSOaw4%2bmk7anP%2fWHf%2foFyHB4GRdSSt%2bBQ4CfPLARY2wPz76S83Be7UDlEh8QtiogXaDqC%2boLhqmx%2fWVlqwQ%3d) ```csharp // C# 13 中可以直接使用方法组并推断自然类型: var a = Example.Method; // 成功推断为Action(选择第一个匹配的委托类型) // 通过上下文进一步优化推断: List> actions = new() { Example.Method }; // 根据集合类型推断为Action ``` ## 隐式索引访问 在C# 13中允许在对象初始化表达式中使用`^` 运算符(`从末尾`索引)直接为集合元素赋值。 ```csharp public class Numbers { public int[] Datas { get; set; } = new int[8]; } public static void ImplicitIndexAccess() { var countdown = new Numbers() { Datas = { [1] = 0, [2] = 1, // 从 C# 13 开始可以执行下面方式赋值 [^3] = 2, [^4] = 3, [^5] = 4 } }; } ``` ## 异步和迭代器方法中的 ref 与 unsafe 支持 在 C# 13 之前,迭代器方法(使用 `yield return` 的方法)和 `async` 方法不能声明局部 `ref` 变量,也不能使用 `unsafe` 上下文。 在 C# 13 中,`async` 方法可以声明 `ref` 局部变量或 `ref struct` 类型的局部变量。 但不可跨 `await` 或 `yield return` 使用。 同样,C# 13 允许在迭代器方法中使用 `unsafe` 上下文。但是,所有 `yield return` 和 `yield break` 语句都必须在安全的上下文中。 应用场景:提升内存敏感操作(如高性能 Span 处理)的灵活性。 ## allows ref struct 在 C# 13 之前,`ref struct` 类型不能声明为泛型或方法的类型参数。现在,泛型类型声明可以添加反约束 `allows ref struct`。 此反约束声明为该类型参数提供的类型参数可以是 `ref struct` 类型。编译器会对该类型参数的所有实例执行 `ref` 安全规则。 - 应用场景:适用于游戏引擎、实时数据处理等需要低延迟内存操作的领域。通过泛型约束,可编写同时支持 `ref struct` 和非 `ref struct` 的通用代码。 例如,可以像下面的代码一样声明一个泛型类型: ```csharp public class C where T : allows ref struct { // 使用 T 作为 ref struct: public void M(scoped T p) { //参数 p 必须遵循 ref 安全规则 } } ``` allows ref struct 反约束声明相应的类型参数可以是 ref struct 类型。 该类型参数的实例必须遵循以下规则: - 它不能被装箱。 - 它参与引用安全规则。 - 不能在不允许 ref struct 类型的地方使用实例,例如 static 字段。 - 实例可以使用 scoped 修饰符进行标记。 ## partial类型中现在允许使用部分属性和索引器 现如今可以在 C# 13 中声明 `partial属性`和`partial索引器`。`partial`属性和索引器通常遵循与`partial`方法相同的规则:创建一个定义声明,一个实现声明。这两种声明的签名必须匹配。一个限制是,不能使用自动属性声明来实现部分属性。未声明正文的属性被视为声明声明。 > > > 注意:不允许对构造函数、终结器、重载运算符或事件声明使用 partial 关键字。在 C# 13 之前,不允许对属性或索引器使用partial。 > ```csharp public partial class MyClass { public partial string Name { get; set; } } public partial class MyClass { private string _name; public partial string Name { get => _name; set => _name = value; } } ``` ## 重载解析优先级 在 C# 13 中,编译器识别 `OverloadResolutionPriorityAttribute`,以便优先选择一个重载而不是另一个。库作者可以使用该属性确保新的、更好的重载比现有的重载更受青睐。 应用场景:适用于解决特定场景下的重载冲突和性能优化需求。通过合理设置优先级,开发者可以在保持代码兼容性的同时,优化编译器的选择逻辑。 ```csharp public class Printer { [OverloadResolutionPriority(1)] //优先调用 public static void PrintWay(params int[] numberList) { } public static void PrintWay(params ReadOnlySpan numberList) { } } ``` ## 参考文章 - ![](https://cdn.res.knowhub.vip/c/2503/29/7bbb50f9?G0IAAETd9LxqED%2b%2fT6qjO9aKDQhrTXzpCChJoauM3NmBcvgo36snMh7%2b8LffRB0z6IvQtHE2rg2m%2bLqI1AY%3d)