当前位置: 首页 > 科技观察

说说我最喜欢的Dotnet5.0&C#9

时间:2023-03-19 16:20:06 科技观察

本文转载自微信公众号“老王加”,老王加作者老王。转载本文请联系老王Plus公众号。C#9,对应于Dotnet5.0。这个出来有段时间了,不过好像群里很多人还没上过这个版本。我这边现在已经全线转5.0了,还是我常说的原因:爽。Dotnet的每一次升级都有一些惊人的特性,使代码更加合理,节省了时间。1.在基础语言方面,在语言方面,最重要的特点是Record。这是C#9出来的一种新的数据类型。没错,Record是一种数据类型。这个Record提供了一些很酷的内置函数来表示数据,因此在使用时感觉更像一个类。据微软称,Record的目的是提供一种更小、更简单的类型来表示不可变数据。但是在使用中,我更喜欢用它来进行数据传输。定义记录有几种方法可以定义记录。最简单的形式是:publicrecordUser(stringname,intage);你第一次看到这个东西,会有点奇怪,不是吗?看起来有点像方法,但是没有内容。嗯,这确实是一个Record的声明式定义,它定义了一个对象user,它有name和age两个属性。可以通过以下方式访问:varsome_user=newUser("WangPlus",35);Console.WriteLine(some_user.name);//OutputWangPlusConsole.WriteLine(some_user.age);//Output35确实有点像类。让我们看一下另一种定义方式,它会更像一个类:类:v??arsome_user=newUser{name="WangPlus",age=35};您还可以使用位置语法进一步简化:Usersome_user=new("WangPlus",35);请注意,此位置语法实际上意味着按位置匹配字段。赋值时会自动寻找对应位置的属性进行匹配校验。此外,对于第一个简单的定义:publicrecordUser(stringname,intage);当真正编译赋值语句时,上面字段中的set会被init替换,即:publicrecordUser{publicstringname{get;init;}publicintage{get;init;}}这意味着该属性在初始化后无法更改,成为只读属性。EqualityJudgmentRecord对相等的定义是内部属性相等。即判断两个Records是否相等时,会检查每个属性的值,而不是对象的引用地址。参见示例:Usersome_user1=new("WangPlus",35);Usersome_user2=new("WangPlus",35);Console.WriteLine(some_user1==some_user2);//trueConsole.WriteLine(ReferenceEquals(some_user1,some_user2));/在/false示例中,some_user1和some_user2具有相同的属性,因此它们是相等的,尽管它们是两个不同的引用。不同的ToString()Record的ToString是内置方法,与其他对象的ToString有很大区别。它会输出Record的所有定义、属性和值。在上面的例子中,输出将是:User{name=WangPlus,age=35}注意:如果Record的属性是引用类型,ToString将输出该类型的名称。Record值的传递已经扩展到了C#10,相关内容我在《Dotnet6.0,你值得拥有》中有详细的说明,大家可以看看。这里简单说一下,使用With:Usersome_user=new("WangPlus",35);Userother_user=some_userwith{name="WangPlus1"};定义Init属性在C#9中,添加了一个用于属性定义的新init关键字。Struct、Class、Record中都可以使用该关键字,表示该属性只能在初始化时设置。例如:publicrecordUser{publicstringname{get;set;}publicintage{get;init;}}这里,age属性被定义为init。赋值还是一样的:Usersome_user=new("WangPlus",35);更改值时,例如:some_user.name="WangPlus1";这是有效的,但是:some_user.age=36;这句话会报错,因为在上面的定义中,age被定义为init,即只能在初始化的时候赋值。以上是C#9中最重要的新增内容:Record类型。2.APIAPI方面,主要有三个特点。1).热门节目这是大家期待已久的一个功能。在早期,程序的开头看起来像这样:usingSystem;namespaceDemo{staticclassProgram{staticvoidMain(string[]args){Console.WriteLine("HelloWorld!");}}}级程序,这一大段可以直接简化为:System.Console.WriteLine("HelloWorld");没关系。Program、Main,都可以省略。WebAPI应用程序也是如此:usingMicrosoft.AspNetCore.Hosting;usingMicrosoft.Extensions.Hosting;namespaceDemo{publicclassProgram{publicstaticvoidMain(string[]args){CreateHostBuilder(args).Build().Run();}publicstaticIHostBuilderCreateHostBuilder(string[]args)=>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder=>{webBuilder.UseStartup();});}}这是标准WebAPI应用程序的开始。现在,也可以简化为:usingMicrosoft.AspNetCore.Hosting;usingMicrosoft.Extensions.Hosting;CreateHostBuilder(args).Build().Run();IHostBuilderCreateHostBuilder(string[]args)=>Host.CreateDefaultBuilder(args)。ConfigureWebHostDefaults(webBuilder=>{webBuilder.UseStartup();});这种代码其实更简洁,能直观的说明程序的意图。如果您也经常编写Python,您会喜欢这个功能。2).新的匹配模式在C#9中,终于添加了期待已久的新匹配模式。主要有两大类:第一类:逻辑匹配,主要包括And、Or、Not。以前我们会用这样的判断:if(input==null){}有时候,我们也会写成:if(inputisnull){}但是判断不相等的时候,我们只有一种方法,即:if(input!=null){}现在,我们有了一种更易读的写法:if(intisnotnull){}看起来可读性很强。第二类:关系匹配的特征涉及到<、>、<=、>=,最重要的是改变Switch。以前使用Switch时,Case必须是可枚举值。看例子:switch(input){case1:break;case2:break;default:break;}现在这里加了一个范围判断,可以写成这样:switch(input){case<5:break;case>=5and<=9:break;default:break;}看到了吗?更多的逻辑可以在Switch中实现,而不是一个大的if…else。3).类型省略这个特性涉及代码的方方面面,主要目的是减少代码输入量。看一个例子,在我们定义一个字段之前,通常是这样的:publicListusers=newList();现在,我们可以直接省略后面的部分,编译器会很聪明地知道我们要New什么:publicListusers=new();方法是一样的。假设我们有一个方法:publicstaticclassUsers{publicUsercopyUser(Usersource){}}之前调用的时候需要先给一个变量,然后调用方法:Usersource_user=newUser();Users.copyUser(source_user);现在,我们可以在方法中直接新建:Users.copyUser(new());当然,这个特性也结合了上面Record的特性。因此,我们也可以这样写:Users.copyUser(new(){name="WangPlus"});好吧,语言的变化需要一点时间来适应,但从长远来看,它仍然是一种改进,可以使代码更易于编写和阅读。同时这个特性和var会成为编程的两个方面,哪个更好用就看你自己的习惯了。3.总结总的来说,Dotnet5.0的变化还是有很多惊喜的。上面写的只是我们比较容易感受到的部分,感觉不到的部分,比如编译的合理性、性能优化、GC回收等,都做得很好。早转5.0早上好吧?