C# 12
前言
C# 12 是 .NET 8 版本推出的,目前还在 RC 阶段。预计 2023 年 11 月份就会正式推出了。
想提早玩玩的话可以使用用 Visual Studio Preview。
参考
Primary Constructors
参考:
Docs – Tutorial: Explore primary constructors
YouTube – The New Constructor Type Coming in C# 12 is Weird
C# 9.0 推出的 Record 就有 Primary constructors 的概念。
它的 definition 非常短
public record Dimension(int Width, int Height);
相同的逻辑,class 就很长很繁琐。
public class Dimension { public int Width { get; set; } public int Height { get; set; } public Dimension(int width, int height) { Width = width; Height = height; } }
于是,C# 12 也让 class 和 struct 有了 primary constructors 的功能。
但是要注意哦,它们有一些些微妙的不同,很容易让你掉坑。
Class primary constructors != Record primary constructors
public class Dimension(int width, int height);
上面这句和 Record 语法类似,但是效果却差很多。
首先,它的参数是 camelCase,Record 是 PascalCase,为什么呢?
因为 Record 的参数是 public property,而 class 的 parameter 是 private field。
所以,property 的写法应该是长这样的。
public class Dimension(int width, int height) { public int Width { get; set; } = width; public int Height { get; set; } = height; }
不管怎样,它还是比之前短了一些。还是不错用的。
Parameters can be use anywhere
参数不仅仅可以用于 assign to property,它也可以在方法中使用。
public class Dimension(int width, int height) { public int Sum() { return width + height; } }
原因上面提到了,paramters 其实是 private filed 来的
我们把代码放到 sharplab.io 查看就明白了
简单说,primary constructors 就是语法糖,它就是替你写了一个 constructor 还有 private fields.
Dependency Injection
C# 11
public class Dimension { private readonly Service _service; public Dimension(Service service) { _service = service; } }
C# 12
public class Dimension(Service service) { private readonly Service _service = service; }
如果你不是很在意 readonly 的话,可以省略
public class Dimension(Service service) { }
本来听说会支持 readonly 语法
public class Dimension(readonly Service service) { }
但最后视乎是被否决掉了。
总结
C# 12 以后,Record, Class, Struct 又又又更加像了,更傻傻分不清楚了,更容易掉坑了。
记住,class 的 primary constructors 是 constructor + private fields, Record 则是 constructor + public properties。
Collection Expressions
日常我们定义 collection 的方式
var numbers = new List<int> { 1, 2, 3 };
上面是 var 推导类型的 defined 写法
换成先 declare 类型是这样
List<int> numbers = new() { 1, 2, 3 };
C# 12 对上面这句语法又做了优化,现在只需要这样写
List<int> numbers = [1, 2, 3];
单纯比长度的话,本来只是少了 var 现在又少了 new 确实短了不少。var 剩下的唯一好处就只有起头字数一样,可以对齐。
它只是语法糖而已,通过 sharplab.io 查看
转译出来就是 new List + add item
Spread Operator
写过 JavaScript 的人对 spread operator 应该不陌生了。C# 12 也有了这个功能。
var numbers = new List<int> { 1, 2, 3 }; List<int> numbers2 = [..numbers, 4, 5]; // 语法正确 var number3 = new List<int> { ..numbers2, 6, 7 }; // 语法错误哦
Default lambda parameters
C# 11 lambda 是不支持 default parameter value 的。C# 12 以后支持了。
C# 12
如何动态创建表达式树 for default parameters 我还没有研究。以后补上。
Alias any type
Alias type 有点像 TypeScript 的 Type Aliases,但也不完全一样。
它的写法长这样
using Point = Coordinate; public class Coordinate { public int X { get; set; } public int Y { get; set; } }
它可以完全用一个 alias 别名取代任何类型,就真的是 rename 而已哦。
var point = new Point();
上面这个在 C# 是 ok 的,但在 TypeScript 是做不到的。
使用场景我还没有什么体会,目前看到的第一个好处是可以用来 define Tuple。
using Person = (string Name, int Age); public class Service { public void DoSomething(Person[] people) { var service = new Service(); service.DoSomething([("Derrick", 1)]); } }
这个应该是最短的写法了。从前至少都要使用 Record,而 Record 是需要 new () 的,上面连 new 都不需要了。
局限
目前看到 2 个局限
1. using 的位置只能在最顶部,这个不够方面。
2. alias 不可用于 alias
using Person = (string Name, int Age); using People1 = Person[]; // Error: The type or namespace name 'Person' could not be found using People2 = List<Person>; // Error: The type or namespace name 'Person' could not be found
上面 2 个写法都不支持。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析