再来说说我喜欢的 Dotnet 5.0 C# 9

上次写完 C# 10,有兄弟在后台问 C# 9,就再开个篇写一写。

C# 9,对应的是 Dotnet 5.0。

这个出来也有些日子了,不过好像群里很多人还是没往这个版本走。

我这边现在是全线已经转向了 5.0,还是我经常说的那个原因:爽。Dotnet 的每一次升级,都有一些让人惊喜的特性,让代码更合理,更节省时间。

1. 基础语言方面

语言方面,最主要的特性,是 Record。这是 C# 9 出来的一个新数据类型。没错,Record 是一个数据类型。

这个 Record 提供了一些很爽的表示数据的内置功能,以至于使用的时候,感觉它更像一个类。

按微软的说法,Record 的目的,是提供一个更小更简单的类型来表示不可变数据。不过在使用中,我更喜欢用它来做数据传输。

定义一个 Record

定义一个 Record 有几种方式。最简单的形式是:

public record User( string name, int age );

第一次看这个东西,会有点奇怪,有没有?长得有点像方法,可就没内容。

嗯,这确实是 Record 的一个声明定义,定义了一个对象 user,这个对象 user 具有 name 和 age 两个属性。可以通过以下方式来访问:

var some_user = new User ( "WangPlus", 35 );
Console.WriteLine( some_user.name );    //输出 WangPlus
Console.WriteLine( some_user.age );        //输出 35

确实跟类有点像。

再来看看另一种定义方式,会更像一个类:

public record User
{public string name { get; set; }public int age { get; set; }
}

给 Record 赋值

既然长得像类,我们可以像类一样去赋值:

var some_user = new User { name = "WangPlus", age = 35 };

还可以用位置语法,近一步简化:

User some_user = new ( "WangPlus", 35 );

注意这个位置语法,其实就是按位置匹配字段的意思。赋值时的值,会自动去找对应位置的属性来匹配和校验。

而且,对于第一种简单定义:

public record User( string name, int age );

赋值语句实际编译时,上面字段中的 set 会被替换为 init,即:

public record User
{public string name { get; init; }public int age { get; init; }
}

这意味着属性在初始化后无法改变,会变成只读属性。

相等判断

Record 对于相等的定义是内部的属性相等。也就是说,判断两个 Record 是否相等时,将检查每个属性的值,而不是对象的引用地址。

看例子:

User some_user1 = new ("WangPlus", 35);
User some_user2 = new ("WangPlus", 35);
Console.WriteLine(some_user1 == some_user2);    // true
Console.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,相关内容我在 「Dotnet 6.0,你值得拥有」里有详细的描述,可以去看看。

这里简单说一下,就是使用 With:

User some_user = new ( "WangPlus", 35 );
User other_user = some_user with { name = "WangPlus1" };

定义 Init 属性

C# 9 里,新增了一个对于属性定义的 init 关键字。这个关键字可以用在 Struct、Class、Record 中,表示属性仅在初始化时可以进行设置。

例如:

public record User
{public string name { get; set; }public int age { get; init; }
}

这里,age 属性被定义为 init。赋值还是一样的:

User some_user = new ( "WangPlus", 35 );

当改变值时,例如:

some_user.name = "WangPlus1";

这个是有效的,但是:

some_user.age = 36;

这句话会报错,因为在上面定义中,age 被定义为 init,即只有初始化时可以赋值。

以上是 C# 9 中增加的最重要的一个内容:Record 类型。

2. API 方面

API 方面,主要是三个特性。

1. 顶级程序

这算是大家盼了很久的一个特性。

早期,一个程序的开始,会是这个样子:

using System;namespace Demo
{static class Program{static void Main(string[] args){Console.WriteLine("Hello World!");}}
}

现在有了顶级程序的规则,这一大段,可以直接简化为:

System.Console.WriteLine("Hello World");

就OK了。Program 啦,Main 啦,统统都可以不写了。

对于 WebAPI 应用也一样:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;namespace Demo
{public class Program{public static void Main(string[] args){CreateHostBuilder(args).Build().Run();}public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();});}
}

这是一个标准的 WebAPI 应用的开始。现在,也可以简化成:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;CreateHostBuilder(args).Build().Run();IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();});

这样的代码其实更简洁,而且可以直观的说明程序的意图。如果你也经常写 Python,那你会很喜欢这个特性。

2. 新的匹配模式

C# 9 里,终于加入了大家期盼已久的新的匹配模式。主要有两类:

第一类:逻辑匹配

这个主要是加入了 And、Or 和 Not。

以前,我们会用到这样的判断:

if( input == null ) {}

有时候,我们也会写成:

if( input is null ) {}

但是,判断不等于时,我们只有一种方式,就是:

if( input != null ) {}

现在,我们有了更可读的写法:

if( int is not null ) {}

看起来可读性就很高了。

第二类:关系匹配

这个特性,涉及的是 <、>、<=、>=,最主要的是改变了 Switch。

以前,使用 Switch 时,Case 必须是可枚举的值,看例子:

switch( input )
{case 1:break;case 2:break;default:break;
}

现在,这里面加入了范围判断,可以这么写:

switch( input )
{case <5:break;case >=5 and <=9:break;default:break;
}

看到没?更多的逻辑可以在 Switch 里实现,而不用一大篇 if…else 了。

3. 类型省略

这个特性涉及到代码的方方面面,主要的目的,是为了减少代码的输入量。

看个例子,以前我们定义一个字段,通常是这样:

public List<User> users = new List<User>();

现在,我们可以直接省略后面的部分,编译器会很聪明的知道我们想 New 什么:

public List<User> users = new ();

方法也是一样。假设我们有一个方法:

public static class Users
{public User copyUser(User source) {}
}

以前调用时,我们需要先给个变量,再调用方法:

User source_user = new User();
Users.copyUser( source_user );

现在,我们可以在方法中直接 New:

Users.copyUser( new () );

当然,这个特性也结合了上面 Record 的特性。

因此,我们还可以这么写:

Users.copyUser( new () { name = "WangPlus" } );

嗯,语庋的改变需要一点时间来适应,但从长远来看,依然是一种进步,会让代码更方便写和读。同时,这个特性,和 Var 会变成编程的两个面,哪个更好用,看自己的习惯了。

3. 总结

总的来说,Dotnet 5.0 的变化还是有很多惊喜的。上面写的,只是我们能比较容易感受到的部分,感受不到的部分,比方编译的合理性、性能的优化,GC的回收,做得都相当优秀。

早转 5.0 早好,对吧?

喜欢就来个三连,让更多人因你而受益

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/297447.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《C语言及程序设计》实践参考——当年第几天(数组方案)

返回&#xff1a;贺老师课程教学链接 项目要求 【项目3-当年第几天(数组方案)】 当年第几天中定义一个函数&#xff0c;其参数为年、月、日的值&#xff0c;返回这一天为该年的第几天。要求在main函数中输入年月日&#xff0c;然后调用这个函数求值&#xff0c;并在main函数中…

开发与研发(转)

按&#xff1a;这几天我一直在写这篇东西&#xff0c;本来是胸有成竹&#xff0c;没想到后来越写越发现自己在这个题目下有太多话想说&#xff0c;而以我现在的能力又不能很好地概括总结&#xff0c;以至于越写越长&#xff0c;文章结构也变得混乱&#xff0c;到后来修改的时候…

java和python哪个学习编程_初学编程,选Java还是Python?

从岗位需求量的角度目前Java仍然是最火的编程语言&#xff0c;在编程语言排行榜中Java常年稳居第一&#xff0c;和他不相上下的C语言&#xff0c;是面向过程的编程语言&#xff0c;简言之面向过程的语言适合于那些有强大数学基础、逻辑学基础的人。如果你学编程的目的是打算上班…

sql 百分数_SQL经典50题笔记

SQL语句执行顺序(8) SELECT (9)DISTINCT<Select_list> (1) FROM <left_table> (3) <join_type>JOIN<right_table> (2) ON<join_condition> (4) WHERE<where_condition> (5) GROUP BY<group_by_list> (6) WITH {CUBE|ROLLUP} (7) HAV…

Android 横竖屏切换的处理 (转载)

Android 中&#xff0c;缺省情况下屏幕的切换动会销毁当前的Activity&#xff0c;并且重启Activity。当然这种缺省的处理方式可能不符合我们的要求。 可以有多种选择改变这种处理方式。 一种方式是在销毁Activity前保存数据&#xff0c;在Activity再次Create的时候载入配置。on…

这种秀恩爱你见过吗?

1 棒棒哒&#xff0c;做的好2 程序员的日常3 一群单身鱼都看呆了4 最佳COS5 自拍达喵6 为什么你们能长这么大&#xff1f;懵逼了7 请用一个词形容这张图你点的每个赞&#xff0c;我都认真当成了喜欢

Layui宣布下线,不自禁的感叹一下,回忆啊

简单唠唠 其实对于前端的信息好久没关注了&#xff0c;一堆后端的Bug要撸&#xff0c;实在没有时间&#xff1b;由于浏览器收藏的东西比较多&#xff0c;于是就想抽点时间归归类&#xff0c;方便查询信息&#xff1b;趁这个机会就挨个点进去瞅一遍&#xff08;随便摸摸鱼&#…

《C语言及程序设计》程序填空——字符数组与字符串处理

返回&#xff1a;贺老师课程教学链接 1、编写一函数&#xff0c;由实参传来一个字符串&#xff0c;统计此字符串中字母、数字、空格和其它字符的个数&#xff0c;在主函数中输入字符串以及输出上述的结果。请将下面的程序补充完整。#include<stdio.h> #include<string…

csv文件设置每个cell大小_Python对文本文件和Excel的处理机制

有头发且有趣的码农万里挑一~ 96有料叔 | 一位有故事的程序猿读取文件内容的方式直接一次性读取文件内容按行读取文件内容将读取的文件内容形成一个列表直接一次性读取文件内容open()需要手动释放资源&#xff0c;最后使用close()with open() as…使用with … as…&#xff0c;…

给图片添加水印

许久没写代码了&#xff0c;许久没上博客园了&#xff0c;许久没有写博文了。using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Drawing.Drawing2D;using System.Drawing.Imaging;using Syste…

idea2020.2.2怎么创建web项目_创建Vue3.0的项目

1. 查看Vue的环境版本Vue -V如果版本低于4.0&#xff0c;则需要升级Vue的版本npm install -g vue/cli2. 创建Vue 3.0的项目3. VS Code 的环境配置安装Extension&#xff1a;ESLint&#xff0c; Vetur。VS Code基于ESLint的Auto Save功能&#xff0c;可以很好的格式化代码&#…

揭秘奢侈品代工厂内幕:千元以上的大牌墨镜,成本甚至不过百!

▲ 点击查看纵观全球没有哪个国家像中国这样几乎所有领域都在发力世界能研发高铁的国家&#xff0c;不超过十个&#xff0c;中国在列&#xff1b;世界能建造军舰的国家&#xff0c;不超过十个&#xff0c;中国在列&#xff1b;世界能研发第五代隐身战机的国家&#xff0c;不超过…

Dapr牵手.NET学习笔记:状态管理进阶(一)

在上一篇文章中说到&#xff0c;dapr默认的状态是不可能跨appid的&#xff0c;也就是只能在相同的应用内访问自己设置的状态数据&#xff0c;dapr支持三种状态的共享配置&#xff1a;appid&#xff0c;nam&#xff0c;none&#xff0c;是通过修改components下的statestore.yaml…

[WP] 关于页面切换动画 记录

1 app.xmal.cs 部分修改如下 private void InitializePhoneApplication() {if (phoneApplicationInitialized)return;// Create the frame but dont set it as RootVisual yet; this allows the splash// screen to remain active until the application is ready to r…

ext 浅谈类的实例

打开ext的API&#xff0c;如下找到Class这个选项将鼠标移到config那里可以看到有以下属性&#xff1a;好了&#xff0c;让我们开始进入主题&#xff1a;首先&#xff0c;来讲讲如何自定义一个类&#xff0c;在ext中&#xff0c;创建一个类其实与其他语言差不多&#xff0c;只是…

GAE 随机获取实体

有时我们需要随机地获取数据记录&#xff08;实体&#xff09;&#xff0c;比如博客程序中的“随机文章”的实现。 目前 GAE 并没有 API 可以直接获取随机实体&#xff0c;要实现这样的需求我们只能自己想办法了 :-) 在 stackoverflow 上也有人提过该问题&#xff0c;总结如下&…

构造函数怎么在主函数调用_C++ 虚基类及其派生类构造函数(学习笔记:第7章 12)...

虚基类及其派生类构造函数[1]建立对象时所指定的类称为最远派生类。虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。在整个继承结构中&#xff0c;直接或间接继承虚基类的所有派生类&#xff0c;都必须在构造函数的成员初始化表中为虚基类的构造函…

打得了橄榄球大联盟,进得了麻省理工,无论是四肢还是头脑都同样发达,这才叫猛男!...

全世界只有3.14 % 的人关注了爆炸吧知识今天小天就介绍一位同样在学术界、体坛都很生猛的猛男吧约翰尤索 (John Urschel) 关于约翰尤索一直有“学霸”“学神”这些词伴随着他然而尤索却说他从来都没认真听过老师讲课尤索出生在加拿大温尼伯父亲是医生&#xff0c;母亲是律师很小…

如何使用 EF Core 按周 对数据分组?

咨询区 Aza&#xff1a;在 Entity Framework 6 中&#xff0c;我可以用 SqlFunctions.DatePart() 函数来实现&#xff0c;参考如下代码&#xff1a;var byWeek data.GroupBy(x > SqlFunctions.DatePart("week", x.Date));现在的问题是, Entity Framework Core 中…

忍着疼痛奔跑,带着泪光微笑!

忍着疼痛奔跑&#xff0c;带着泪光微笑转瞬&#xff0c;毕业已近四年&#xff0c;回顾&#xff0c;还在路上。头几年&#xff0c;有着一颗爱玩的心&#xff0c;秉着“人这一辈子不能对不起自己”的谬论&#xff0c;一直随着自己的性子&#xff0c;想做什么就做什么&#xff0c;…