上次写完 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 早好,对吧?

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

再来说说我喜欢的 Dotnet 5.0 C# 9相关推荐

  1. Dotnet 6.0 深度探索(一)

    Dotnet 6.0 已来. Dotnet 6.0 大家都装了没? 我打算开个专题,系统地写一写 Dotnet 6.0 在各个方面的特性,以及全新的开发方式.也是因为最近讨论 6.0 比较多,看到很多 ...

  2. Dotnet 6.0,你值得拥有

    Dotnet 6.0 就要来了,这会是一个绝对值得拥有的版本.了解一下?   最近在研究 Dotnet 6.0 & C# 10,一个字 - 爽! 下面,分享一下新的一些特性给大家. 一.编程语 ...

  3. 一. DotNet MVC4.0+EasyUI Web简单框架-前言

    之所以说它简单,是因为仅仅用了大家最熟悉的三层架构,简单明了 1.先新建一个MVC4.0 Web项目 2.添加EasyUI的引用,放到Script底下 http://files.cnblogs.com ...

  4. Dotnet 2.0配置系统

    今天使用VS2005开发一个Windows服务,发现dotnet2.0的配置系统相对于1.x的功能变化很大.记录下来同各位共享. .NET Framework 1.1 提供一个基本的应用程序配置机制, ...

  5. 如何使用DotNet 2.0中的应用程序配置 Settings.settings

    对于桌面应用程序,常常会需要记录一些用户配置信息,早期的做法一般是使用读写INI文件的办法.     对于.NET应用程序,并没有提供直接操作INI文件的类,需要调用Win32API,具体办法可以参考 ...

  6. DotNet Core 2.0部署后外网IP访问

    将DotNet Core2.0项目部署在Ubuntu上并且运行后,可以用localhost:5000来访问. 但是如果这时候用外网来访问就不行了. 这时候就有两种解决方案,第一种是用Nginx做代理实 ...

  7. [问题]DotNet 项目如何实现在构建时 Build 号自动增加?

    [问题]DotNet 项目如何实现在构建时 Build 号自动增加? 继续昨天的问题,今天在Google上找了一下,没有找到很好的方案. 目前找到的解决方案有以下几种: 1.使用一个地三方的 VS.N ...

  8. Dotnet Core应用跨框架版本运行

    有时候,我们真想用新框架,可也真不想改代码.   有一个前置的知识需要了解,就是微软 Dotnet Core 框架的版本体系.我前边的文章「Dotnet Core使用特定的SDK&Runtim ...

  9. .NET 5.0 RC1 发布,离正式版发布仅剩两个版本,与 netty 相比更具竞争力

    原文:http://dwz.win/Qf8 作者:Richard 翻译:精致码农-王亮 说明: 1. 本译文并不是完全逐句翻译的,存在部分语句我实在不知道如何翻译或组织就根据个人理解用自己的话表述了. ...

最新文章

  1. node/js 漏洞_6个可用于检查Node.js中漏洞的工具
  2. linux下ifconfig, DNS以及route配置
  3. 如何用python开发游戏_手把手教你用Python完成一个控制台小游戏-阿里云开发者社区...
  4. 【渝粤教育】广东开放大学 商务英语听说 形成性考核 (37)
  5. 剑指offer:22-25记录
  6. 基本的 HTML 标签
  7. hdu 4599 Dice
  8. PDF Candy Desktop(全能PDF工具箱)官方中文版V2.91 | pdf candy desktop官网下载 | 含pdf candy desktop使用教程
  9. DAMS峰会丨从数仓到数据中台,从数据资源到资产,京东、携程、快手等是怎么建设和演进的?...
  10. Windows操作系统单网卡设置双IP
  11. 百兆网络变压器原理图及网络变压器功能(附PDF工程图纸)
  12. 我的世界服务器矿怎么无限刷,我的世界中可以无限刷矿的指令是什么quest; | 手游网游页游攻略大全...
  13. 钉钉发起审批流程分析
  14. 【Google Paper】对比学习用于解决推荐系统长尾问题
  15. PHPstudy mysql secure_file_priv 设置
  16. 学习篇-Activiti-29-流程定义存储表
  17. 骑士周游(马踏棋盘)问题
  18. 王子与公主的爱情故事新结局(转)
  19. 迪克体育Dick’s Sporting Goods EDI需求分析
  20. ## IDEA创建maven项目没有src目录问题解决

热门文章

  1. MegaCli 监控Raid状态
  2. [原创]FineUI秘密花园(二十七) — 窗体控件概述(上)
  3. User Experience Kit
  4. linux批量杀进程_Linux下批量杀JAVA进程
  5. h5c3 part6 flex
  6. 【转】博客美化(1)基本后台设置与样式设置
  7. .net post xml 数据
  8. GChemPaint-绘制化学分子布局
  9. ubuntu 任务栏监视器_从系统任务栏监视Google服务
  10. 如何在Windows 10中将您喜欢的设置固定到开始菜单