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

【.NET新特性·第6篇】C# 13 新特性全解:10 个改变你编码方式的特性

C# 13 带来了 params 集合、新 Lock 类型、ref struct 突破等 11 个新特性

版本定位

适用版本:.NET 9 | C# 13 前置知识:C# 12 基础

背景

C# 13 是继 C# 12 之后的又一次重要更新。这次更新的重点是泛型系统的突破性能优化。ref struct 可以实现接口、泛型支持 ref struct 类型参数,这些改变让 C# 的类型系统更加强大。

C# 13 新特性一览

特性简述实用性
params 集合params支持Span<T>IEnumerable<T>⭐⭐⭐⭐⭐
新 Lock 类型System.Threading.Lock替代Monitor⭐⭐⭐⭐⭐
\e 转义序列新的转义字符⭐⭐⭐
method group 自然类型方法组推断改进⭐⭐⭐
ref struct 实现接口ref struct 可以实现接口⭐⭐⭐⭐
allows ref struct泛型支持 ref struct⭐⭐⭐⭐
partial 属性属性和索引器支持 partial⭐⭐⭐⭐
overload 优先级库作者可以指定重载优先级⭐⭐⭐
ref locals in iterators迭代器中支持 ref 局部变量⭐⭐⭐
field keyword(预览)字段关键字预览⭐⭐⭐⭐
隐式索引器访问对象初始化器中使用[^]语法⭐⭐⭐⭐

特性详解

1. params 集合

之前的做法params只支持数组

// C# 12 及之前 void PrintAll(params string[] items) { foreach (var item in items) { Console.WriteLine(item); } } PrintAll("a", "b", "c"); // OK // PrintAll([1, 2, 3]); // 编译错误

C# 13 的做法params支持所有集合类型

// C# 13 void PrintAll(params string[] items) { /* ... */ } void PrintAll(params List<string> items) { /* ... */ } void PrintAll(params ReadOnlySpan<string> items) { /* ... */ } void PrintAll(params IEnumerable<string> items) { /* ... */ } // 现在可以用集合表达式 PrintAll(["a", "b", "c"]); // OK,适用于所有重载

性能优势

  • Span<T>避免堆分配

  • 编译器优化,减少内存拷贝

2. 新 Lock 类型

之前的做法:使用Monitorlock语句

// C# 12 及之前 private readonly object _lock = new(); void DoWork() { lock (_lock) { // 临界区 } } // 或者显式使用 Monitor void DoWorkExplicit() { Monitor.Enter(_lock); try { // 临界区 } finally { Monitor.Exit(_lock); } }

C# 13 的做法:使用System.Threading.Lock

// C# 13 private readonly Lock _lock = new(); void DoWork() { lock (_lock) // 自动使用新的 Lock 类型 { // 临界区 } } // 或者显式使用 void DoWorkExplicit() { using var scope = _lock.EnterScope(); // 临界区 }

优势

  • 更好的性能

  • 更清晰的语义

  • 防止 lock 对象被错误转换

3. \e 转义序列

// C# 12 及之前 char esc = '\x1b'; // 十六进制 char esc2 = ''; // Unicode // C# 13 char esc = '\e'; // 新的转义序列

4. method group 自然类型

// C# 13 改进了方法组的类型推断 void Process<T>(Action<T> action) { /* ... */ } // C# 12 可能需要显式类型 Process<int>(x => Console.WriteLine(x)); // C# 13 可以推断类型 Process(x => Console.WriteLine(x)); // 编译器推断 T 为 int

5. ref struct 实现接口

之前的做法:ref struct 不能实现接口

// C# 12 及之前 ref struct MyStruct { public int Value; } // 不能实现接口 // interface IDisposable { void Dispose(); } // ref struct MyStruct : IDisposable { ... } // 编译错误

C# 13 的做法:ref struct 可以实现接口

// C# 13 ref struct MyStruct : IDisposable { public int Value; public void Dispose() { // 清理资源 } } // 使用 void Process<T>(T item) where T : IDisposable { item.Dispose(); } var myStruct = new MyStruct { Value = 42 }; Process(myStruct); // OK

6. allows ref struct

之前的做法:泛型不支持 ref struct

// C# 12 及之前 void Process<T>(T item) where T : struct { // 不能使用 ref struct } // Process<MyRefStruct>(myStruct); // 编译错误

C# 13 的做法:泛型支持 ref struct

// C# 13 void Process<T>(T item) where T : allows ref struct { // 可以使用 ref struct } Process<MyRefStruct>(myStruct); // OK

7. partial 属性和索引器

// C# 13 partial class MyClass { partial int Count { get; set; } partial int this[int index] { get; set; } } // 源生成器可以实现这些成员 partial class MyClass { partial int Count => _internalCount; partial int this[int index] => _internalArray[index]; }

8. overload 优先级

// 库作者可以指定重载优先级 public class MyService { [OverloadResolutionPriority(1)] public void Process(int value) { /* 高优先级 */ } [OverloadResolutionPriority(0)] public void Process(object value) { /* 低优先级 */ } } // 调用时优先选择高优先级的重载 var service = new MyService(); service.Process(42); // 调用 Process(int),而不是 Process(object)

9. ref locals in iterators

// C# 13 IEnumerable<int> Process(Span<int> data) { ref int first = ref data[0]; first = 100; // OK yield return first; }

10. field keyword(预览)

// C# 13 预览 public class Person { public string Name { get => field; set => field = value?.Trim() ?? string.Empty; } }

11. 隐式索引器访问(Implicit indexer access from object initializers)

之前的做法:对象初始化器中不能使用索引器语法

// C# 12 及之前 var list = new List<string>(); list.Add("a"); list.Add("b"); list[list.Count] = "hello"; // 必须在对象初始化器外赋值 // 或者使用集合初始化器 var dict = new Dictionary<string, int> { ["key1"] = 1, ["key2"] = 2 }; // 但不能在对象初始化器中使用索引器

C# 13 的做法:对象初始化器中支持隐式索引器访问

// C# 13 // 数组 var array = new string[10]; array[^1] = "last element"; // 等价于 array[array.Length - 1] // 在对象初始化器中使用 var list = new List<string> { [^1] = "hello" }; // 与属性初始化结合 var grid = new Grid { [0, 0] = "A1", [0, 1] = "A2", [1, 0] = "B1" };

使用场景

// 集合初始化 var stack = new Stack<int> { [^1] = 10, // 压栈操作的语法糖 [^1] = 20 }; // 矩阵初始化 var matrix = new Matrix(3, 3); matrix[^1, ^1] = 1.0; // 设置右下角元素 // 字符串缓冲区 var buffer = new char[100]; buffer[^1] = '\0'; // 设置结束符

实战场景

params 集合适合的场景

// 日志方法 void Log(params string[] messages) { foreach (var msg in messages) Console.WriteLine($"[{DateTime.Now}] {msg}"); } // 现在可以用集合表达式 Log(["Error", "Warning", "Info"]);

新 Lock 类型适合的场景

// 缓存管理 public class Cache<T> { private readonly Lock _lock = new(); private readonly Dictionary<string, T> _cache = new(); public T GetOrAdd(string key, Func<T> factory) { lock (_lock) { if (!_cache.TryGetValue(key, out var value)) { value = factory(); _cache[key] = value; } return value; } } }

ref struct 接口适合的场景

// 高性能解析器 ref struct JsonParser : IDisposable { private ReadOnlySpan<char> _json; public JsonParser(ReadOnlySpan<char> json) { _json = json; } public void Dispose() { // 清理资源 } } // 可以与泛型方法配合使用 void Process<T>(T parser) where T : IDisposable { using (parser) { // 处理数据 } }

隐式索引器访问适合的场景

// 游戏开发中的网格初始化 var board = new ChessBoard { [0, 0] = new Rook(Color.White), [0, 1] = new Knight(Color.White), [7, 0] = new Rook(Color.Black), [7, 1] = new Knight(Color.Black) }; // 配置文件解析 var config = new Config { ["database.host"] = "localhost", ["database.port"] = "5432", ["cache.enabled"] = "true" }; // 数据结构初始化 var ringBuffer = new RingBuffer<int>(100); ringBuffer[^1] = 42; // 直接设置最后一个位置

迁移建议

自动迁移

C# 13 特性大部分向后兼容:

<PropertyGroup> <LangVersion>13</LangVersion> </PropertyGroup>

需要注意的 breaking changes

  1. Lock 类型:如果代码检查lock对象的类型,可能会受影响

  2. method group:类型推断可能推断出不同的类型

  3. overload 优先级:可能改变现有代码的重载选择

  4. 隐式索引器访问:如果代码中已有类似语法,可能会产生歧义

一句话总结

C# 13 是泛型系统的突破,ref struct 实现接口和 allows ref struct 让 C# 的类型系统更加强大。


官方文档

  • What's new in C# 13

  • params collections

  • New lock type

  • ref struct interfaces


📦示例代码:.NET 新特性巡礼全系列配套示例代码(含 dotnet 8/9/10)

  • GitHub:GitHub - LadyKiller1025/dotnet-feature-tour-demos: .NET Feature Tour - Code Demos (.NET 8/9/10) · GitHub

  • Gitee:https://gitee.com/qakjhzx/dotnet-feature-tour-demos

💬 欢迎点赞、收藏、转发,你的支持是我持续创作的动力!

http://www.gsyq.cn/news/1604943.html

相关文章:

  • TAS54x4A评估模块实战:从硬件连接到软件调试的完整指南
  • 大文件分片上传:从原理到实战,解决Web开发中的传输难题
  • 《深入理解计算机系统》CSAPP八大实验通关指南与实战解析
  • 凑微分,幂等公式
  • GeoTools 多模块依赖最佳实践:一次 OrderedAxisAuthorityFactory 初始化失败的深度复盘
  • Nacos 注解全解析:7 个核心注解 + 5 个生产踩坑清单(2026 实测)
  • go: Deadline Pattern
  • 万字干货|2026 Go 后端通关学习路线,从底层原理到微服务面试全覆盖(附 Code Review 规范 + 线上故障排查方案)
  • 论文阅读笔记 | Thinking in Frames: How Visual Context and Test-Time Scaling Empower Video Reasoning
  • 泛微ECOLOGY9流程主明细行弹窗添加子明细的实现
  • 解除labelstdio数据标注一次上传图片数量限制的方法
  • 如何用N_m3u8DL-RE轻松下载加密流媒体视频:从新手到高手的完整指南
  • TAS3202 DAP架构解析:从定点运算到音频处理实战
  • 终极方案:用xmly-downloader-qt5实现喜马拉雅VIP音频永久保存的完整指南
  • Linux 用户态内存分配:glibc malloc
  • WinUtil:Windows系统优化终极工具 - 一键完成软件安装、系统调优与故障修复
  • 14-already flash encrypt or secure boot提示:ESP32S3误烧熔丝的补救方法
  • 猫抓浏览器扩展:全网视频音频资源一键抓取的终极指南
  • 高颜值出差住地铁口可猫咪的酒店步行 3 分钟到地铁
  • volatile有什么用
  • 告别繁琐操作:原神脚本让你的提瓦特冒险更智能高效
  • PCB 新手 18 类常见错误汇总
  • EtherCAT重学之二: EtherCAT 系统硬件架构
  • 大湾区EMBA特色测评:科学选型理性指南
  • 【LeetCode】第1题 两数之和
  • CBDC安全架构:密码学签名与硬件防护核心技术解析
  • 【单片机毕业设计】基于 STM32 的多模式智能路灯控制系统设计, 基于单片机的光照自适应路灯亮度调节系统设计(014001)
  • 为什么顶尖AI团队拒绝“通用提示词”?——稀缺首发:金融/医疗/法律三大垂直领域217条经审计Prompt资产包(限时开放下载)
  • Java 多线程:继承 Thread 与实现 Runnable 两种创建方式完整对比
  • 自动定期备份服务器数据