c#中嵌入echarts_Build 2020上公布的C# 9.0新特性

本文详细介绍了C#9.0的新增特性,包括init属性访问器简化对象初始化,records和with表达式实现值比较,模式匹配的增强如关系和逻辑模式,以及目标类型化等。这些新特性提升了代码的可读性和灵活性。
摘要由CSDN通过智能技术生成

(给DotNet加星标,提升.Net技能)

转自:MarkKang cnblogs.com/markkang/archive/2020/05/22/12928528.html

在微软的Build 2020开发者大会中,微软就正在成形的C#9.0的一些即将添加的主要特性进行了说明。

一、init属性访问器

对象初始化方式对于创建对象来说是一种非常灵活和可读的格式,特别是对树状嵌入型对象的创建。简单的例如

new Person
{
FirstName = "Scott",
LastName = "Hunter"
}

原有的要进行对象初始化,我们必须要做就是写一些属性,并且在构造函数的初次调用中,通过给属性的setter赋值来实现。

public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}

914a506fd8d1d6be258653c4096a9427.png

二、init属性访问器和只读字段

因为init访问器只能在初始化时被调用,原来只能在构造函数里进行初始化的只读字段,现在可以在属性中进行初始化,不用再在构造函数进行初始化。省略了构造函数。

public class Person
{
private readonly string firstName;
private readonly string lastName;
public string FirstName
{
get => firstName;
init => firstName = (value ?? throw new ArgumentNullException(nameof(FirstName)));
}
public string LastName
{
get => lastName;
init => lastName = (value ?? throw new ArgumentNullException(nameof(LastName)));
}
}

三、Records

f6a93b921e5a20146fc47b4a5875949d.png

四、With表达式

3088f38b545da1913773a0afbc340584.png

var otherPerson = person with { LastName = "Hanselman" };

2e2c053f8befea4fef84d766a9e93bdb.png

五、基于值的相等

95cf60449d7dcf41f62683fa2f614322.png

如果你不喜欢默认Equals重写的字段与字段比较行为,你可以进行重写。你只需要认真理解基于值的相等时如何在records中工作原理,特别是涉及到继承的时候,后面我们会提到。

与基于值的Equals一起的,还伴有基于值的GetHashCode()的重写。

六、data成员

8dc8b61c1b4a64c480258eafa776d780.png

这个使得record声明看起来优美而清晰直观。如果你真的需要一个私有字段,你可以显式添加private修饰符。

private string firstName;

七、Positional records

 在record是可以指定构造函数和解构函数(注意不是析构函数)的。

public data class Person 
{
string FirstName;
string LastName;
public Person(string firstName, string lastName)=> (FirstName, LastName) = (firstName, lastName);
public void Deconstruct(out string firstName, out string lastName)=> (firstName, lastName) = (FirstName, LastName);
}

也可以用更精简的语法表达上面同样的内容。

public data class Person(string FirstName, string LastName);

该方式声明了公开的带有初始化自动属性、构造函数和解构函数,和第6条第一段代码带有大括号的声明方式是不同的。现在你就可以写如下代码:

var person = new Person("Scott", "Hunter"); // positional construction
var (f, l) = person; // positional deconstruction

4161f3cb1890f68dde95828bf2632a82.png

九、with表达式和继承

众所周知,基于值相等和非破坏性变化值的方式在和继承纠结在一起时,非常具有挑战性。下来,我们添加一个继承的record类Student来说明我们的例子:

public data class Person { string FirstName; string LastName; }
public data class Student : Person { int ID; }

下来,我们通过创建一个Student,但是把他存放到Person变量中,来说明with表达式的使用:

Person person = new Student { FirstName = "Scott", LastName = "Hunter", ID = GetNewId() };
otherPerson = person with { LastName = "Hanselman" };

b4a6c607d1e0cbcfd7ebea3ff11fc402.png

然而,相等有着一个格外的挑战,就是如果比较两个不同类型的Person会怎么样?我们不能让他们中一个决定应用哪一个相等性:相等应该是语义的,所以不管两个对象中哪个先来,解构应是相同的。换句话说,他们必须在被应用的相等性达成一致。

这个问题的例子如下:

Person person1 = new Person { FirstName = "Scott", LastName = "Hunter" };
Person person2 = new Student { FirstName = "Scott", LastName = "Hunter", ID = GetNewId() };

b8869f7223a7b3ed90f0147cf3db49ed.png

using System;
class Program
{
static void Main(){
Console.WriteLine("Hello World!");
}
}

这个对于初学者是无法抗拒,但是这使得代码凌乱,大量堆积,并且增加了缩进层级。在C#9.0中,你可以选择在顶级用如下代码代替写你的主程序:

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

451908c29c9f4f59da15b1972b2bafb1.png

十二、增强的模式匹配

C#9.0添加了几个新的模式,如果要了解下面代码段的上下文,请参阅模式匹配教程:

public static decimal CalculateToll(object vehicle) =>
vehicle switch
{
...
DeliveryTruck t when t.GrossWeightClass > 5000 => 10.00m + 5.00m,
DeliveryTruck t when t.GrossWeightClass < 3000 => 10.00m - 2.00m,
DeliveryTruck _ => 10.00m,
_ => throw new ArgumentException("Not a known vehicle type", nameof(vehicle))
};

899367a47dbe9cdcb8f273e3ac916950.png

DeliveryTruck t when t.GrossWeightClass switch
{
> 5000 => 10.00m + 5.00m,
< 3000 => 10.00m - 2.00m,
_ => 10.00m,
},

这的 > 5000 和 < 3000是关系模式。

3、逻辑模式

最后,你可以用逻辑操作符and,or 和not将模式进行组合,来详细说明,以避免表达式操作符引起的混淆。例如,上面嵌入的switch可以按照升序排序,如下:

DeliveryTruck t when t.GrossWeightClass switch
{
< 3000 => 10.00m - 2.00m,
>= 3000 and <= 5000 => 10.00m,
> 5000 => 10.00m + 5.00m,
},

中间的case使用了and 来组合两个关系模式形成了一个表达区间的模式。

not模式的公同使用是它将会被用在null常量模式上,就像not null。例如我们要根据是否为空来分割一个未知的case处理代码段:

not null => throw new ArgumentException($"Not a known vehicle type: {vehicle}", nameof(vehicle)),

null => throw new ArgumentNullException(nameof(vehicle))

not将在包含了is表达式的if条件语句使用也会很方便,并且会取代笨重的双括号:

if (!(e is Customer)) { ... }

你可以这样写:

if (e is not Customer) { ... }

十三、增强的目标类型化

5f4fdd50414e0670f92106819c896cd1.png

Point p = new (3, 5);

2、目标类型化的??和?:

一些时候,条件表达式??和?:在分支中没有明显的共享类型。现有这种情况会失败,但是在C#9.0中,如果各分支可以转换 为目标类型,这种情况时允许的。

Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type

十四、支持协变的返回值

一些时候,在子类的一个重写方法中返回一个更具体的、且不同于父类方法定义的返回类型更为有用,C# 9.0对这种情况提供了支持。

abstract class Animal
{
public abstract Food GetFood();
...
}
class Tiger : Animal
{
public override Meat GetFood() => ...;
}
推荐阅读   点击标题可跳转 C# 9.0特性预览:空参数校验 C# 9.0新特性预览:型推导的new C# 9.0新特性:代码生成器、编译时反射

看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能 

b66fd68970f2e2129a35d627733336b9.png

好文章,我在看❤️

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值