当前位置: 首页 > news >正文

C# 13 中的新增功能实操

前提准备

要体验 C# 13 新增的功能可以使用最新的 Visual Studio 2022 版本或 .NET 9 SDK 尝试这些功能。

Visual Studio 2022安装

  • 适用于 Windows、Mac 和 Linux 的 Visual Studio 和 VS Code 下载

.NET 9 SDK

  • 下载 .NET 9.0 (Linux、macOS 和 Windows) | .NET

params 集合

在 C# 13 中,params 的改进使其从可变数量的数组参数升级为可变数量的集合类型参数。这一改进通过支持高性能集合类型(如Span<T>、ReadOnlySpan<T>)和简化调用语法,显著提升了代码的灵活性和效率。

C# 13 中的 params 集合变得类型更灵活,满足更复杂的应用场景,并且性能得到了进一步的提升。

在 C# 13 之前:

params 仅支持一维数组(如params int[] listparams object[] list)。调用方法时需显式传递数组或数组元素类型的参数的逗号分隔列表。

在 C# 13 中:

params 修饰符并不局限于数组类型。 现在可以将 params 用于任何已识别的集合类型,包括 System.Span<T>、System.ReadOnlySpan<T>,以及那些实现 System.Collections.Generic.IEnumerable<T> 并具有 Add 方法的类型。 除了具体类型外,还可以使用接口 System.Collections.Generic.IEnumerable<T>、System.Collections.Generic.IReadOnlyCollection<T>、System.Collections.Generic.IReadOnlyList<T>、System.Collections.Generic.ICollection<T>和 System.Collections.Generic.IList<T>

        public static void SpanDataPrintRun(){Span<int> originalSpan = [1, 2, 3, 4, 5];SpanDataPrint(originalSpan);}public static void SpanDataPrint<T>(params Span<T> 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://github.com/dotnet/runtime/issues/34812

        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 后面的下一个字符是有效的十六进制数字,则那些字符会成为转义序列的一部分。

    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://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/proposals/csharp-13.0/method-group-natural-type-improvements

// C# 13 中可以直接使用方法组并推断自然类型:
var a = Example.Method; // 成功推断为Action<int>(选择第一个匹配的委托类型)// 通过上下文进一步优化推断:
List<Action<int>> actions = new() { Example.Method }; // 根据集合类型推断为Action<int>

隐式索引访问

在C# 13中允许在对象初始化表达式中使用^ 运算符(从末尾索引)直接为集合元素赋值。

        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 的通用代码。

例如,可以像下面的代码一样声明一个泛型类型:

public class C<T> 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。

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,以便优先选择一个重载而不是另一个。库作者可以使用该属性确保新的、更好的重载比现有的重载更受青睐。

应用场景:适用于解决特定场景下的重载冲突和性能优化需求。通过合理设置优先级,开发者可以在保持代码兼容性的同时,优化编译器的选择逻辑。

    public class Printer{[OverloadResolutionPriority(1)] //优先调用public static void PrintWay(params int[] numberList) { }public static void PrintWay(params ReadOnlySpan<int> numberList) { }}

文章转载自:追逐时光者

原文链接:C# 13 中的新增功能实操 - 追逐时光者 - 博客园

体验地址:JNPF快速开发平台

http://www.dtcms.com/a/351452.html

相关文章:

  • 深入了解AWS Auto Scaling
  • OpenAI API Python实战教程:如何稳定获取结构化 JSON 输出(简易/复杂 双示例)
  • Nginx Ubuntu vs CentOS 常用命令对照表---详解笔记
  • AR技术引领航空制造迈向智能化新时代
  • Java标识符命名规则与规范
  • 32.Attention-注意力机制
  • 【算法--链表题2】19.删除链表的倒数第 N 个节点:通俗详解
  • A股大盘数据-20250826 分析
  • Java大厂面试实战:从Spring Boot到微服务架构的全链路技术剖析
  • 英伟达jetson开发板Ubuntu系统配置显示屏系统脱离手动输入指令自动编译执行操作
  • InnoDB详解2
  • 从混乱到高效:企业如何构建可持续发展的IT工单系统
  • 清分系统在电商中的一些案例
  • nginx-负载均衡
  • GeoServer与GISBox:地理数据服务器对比解析
  • 【STM32】CubeMX(十三):RT-THREAD
  • 脑电分析——学习笔记
  • 常用测试有哪些
  • Spring Boot 集成 Docker 构建与发版完整指南
  • [docker]Failed to initialize NVML: Unknown Error
  • 【C++】用哈希表封装实现unordered_set和unordered_map
  • 深入剖析悲观锁、乐观锁与分布式锁
  • 如何才能使RISC V架构成为机器学习的核心
  • U-Net图像语义分割中梯度下降的直观解释
  • 动态规划:为什么暴力算法会有重复子问题
  • 深度学习自动驾驶BEV【专业名词解释汇总】
  • VS中创建Linux项目
  • Tomcat的VM options
  • 我在TSX开发中的实用指南:从基础到实战
  • Java大厂面试实战:从Spring Boot到微服务架构的全链路技术解析