当前位置:网站首页>说说 C# 9 新特性的实际运用

说说 C# 9 新特性的实际运用

2020-11-09 19:13:00 程序猿欧文

你一定会好奇:“老周,你去哪开飞机了?这么久没写博客了。”

老周:“我买不起飞机,开了个铁矿,挖了一年半的石头。谁知铁矿垮了,压死了几条蜈蚣,什么也没挖着。”

所以,这么丢死人的事,还是不要提了,爷爷从小教导我做人要低调……

 

一转眼,.NET 5 要来了,同时也带来了 C# 9。遥想当年,老周刚接触 .NET 1.1 的时候,才刚上大学;如今已经过去13年了。岁月是把水果刀,从来不饶人啊。

老周很少去写诸如“XXX新特性”之类的文章,总觉得没啥用处。不过,针对 C# 9,老周想说一点什么。

好,在开始之前,老周再次强调一下:这些语言新特性的东西,你千万不要特意去学习,千万不要,不要,不要,重要的事情讲四遍!这些玩意儿你只要看看官方给的说明,刷一遍就能掌握了(刷这个比刷抖音有意义多了),不用去学的。如果你连这些东东也要学习成本的话,我只想说句好唱不好听的话——你的学习能力真的值得怀疑

 

好了,下面开始表演。

第一出:record 类型

record ,我还是用原词吧,我知道有翻译为“记录类型”的说法。只是,只是,老周老觉得这不太好听,可是老周也找不出更好的词语,还是用回 record吧。

record 是引用类型,跟 class 很像(确实差不多)。那么,用人民群众都熟悉的 class 不香吗,为何要新增个 record 呢?答:为了数据比较的便捷。

不明白?没事,往下看。最近有一位热心邻居送了老周一只宠物:

public class Cat {  public string Nick { get; set; }  public string Name { get; set; }  public int Age { get; set; } }

这只新宠物可不简单,一顶一的高级吃货。鱼肉、猪肉、鸡腿、饼干、豆腐、面包、水果、面条、小麦、飞蛾……反正,只要它能塞进嘴里的,它都吃。

接下来,我们 new 两个宠物实例。

// 两个实例描述的是同一只猫   Cat pet1 = new Cat   {    Nick = "松子",    Name = "Jack",    Age = 1   };   Cat pet2 = new Cat   {    Nick = "松子",    Name = "Jack",    Age = 1   };   // 居然不是同一只猫   Console.WriteLine("同一只?{0}", pet1 == pet2);

其实,两个实例描述的都是我家的乖乖。可是,输出的是:

同一只?False

这是因为,在相等比较时,人家关心的类型引用——引用的是否为同一个实例。但是,在数据处理方案中,我们更关注对象中的字段/属性是否相等,即内容比较。

现在,把 Cat 的声明改为 record 类型。

public record Cat {  public string Nick { get; set; }  public string Name { get; set; }  public int Age { get; set; } }

然后同样用上面的 pet1 和 pet2 实例进行相等比较,得到预期的结果:

同一只?True

 

record 类型让你省去了重写相等比较(重写 Equals、GetHashCode 等方法或重载运算符)的逻辑。

实际上,代码在编译后 record 类型也是一个类,但自动实现了成员相等比较的逻辑。以前你要手动去折腾的事现在全交给编译器去干。

假如,有一个 User 类型,用于表示用户信息(包括用户名、密码),然后这个 User 类型在数据处理方案中可能会产生N多个实例。例如你根据条件从EF模型中筛选出一个 User 实例 A,根据用户输入的登录名和密码产生了 User 实例 B。为了验证用户输入的登录信息是否正确,如果 User 是 class,你可能要这样判断:

if(A.UserName == B.UserName && A.Password == B.Password){ ..................}

但要是你把 User 定义为 record 类型,那么,一句话的工夫:

A == B

 

第二出:模式匹配(Pattern Matching)

"模式匹配"这个翻译感觉怪怪滴,老周还没想出什么更好的词语。模式匹配并不是什么神奇的东西,它只是在对变量值进行检测时的扩展行为。以前,老感觉C++/C# 的 switch 语句不够强大,因为传统的用法里面,每个 case 子句只能比较单个常量值。比如

int 考试成绩 = 85;   switch (考试成绩)   {    case 10:     Console.WriteLine("才考这么点破分啊");     break;    case 50:     Console.WriteLine("还差一点,就合格了");     break;    case 85:     Console.WriteLine("真是秀");     break;    case 90:     Console.WriteLine("奇迹发生");     break;   }

我幻想着,要是能像下面这样写就好了:

switch (考试成绩)   {    case 0:     Console.WriteLine("缺考?");     break;    case > 0 && <= 30:     Console.WriteLine("太烂了");     break;    case > 30 && < 60:     Console.WriteLine("还是不行");     break;    case >= 60 && < 80:     Console.WriteLine("还得努力");     break;    case >= 80 && < 90:     Console.WriteLine("秀儿,真优秀");     break;    case >= 90 && <= 100:     Console.WriteLine("不错,奇迹");     break;   }

 

等了很多年很多年(“千年等一回,等……”)以后,终于可以实现了。

switch (考试成绩)   {    case 0:     Console.WriteLine("缺考?");     break;    case > 0 and <= 30:     Console.WriteLine("太烂了");     break;    case > 30 and < 60:     Console.WriteLine("还是不行");     break;    case >= 60 and < 80:     Console.WriteLine("还得努力");     break;    case >= 80 and < 90:     Console.WriteLine("秀儿,真优秀");     break;    case >= 90 and <= 100:     Console.WriteLine("不错,奇迹");     break;   }

哟西,真香。

 

有时候,不仅要检测对象的值,还得深入到其成员。比如下面这个例子,Order类表示一条订单信息。

public class Order {  public int ID { get; set; }  public string Company { get; set; }  public string ContactName { get; set; }  public float Qty { get; set; }  public decimal UP { get; set; }  public DateTime Date { get; set; } }

前不久,公司接到一笔Order,做成了收益应该不错。

Order od = new Order   {    ID = 11,    Company = "大嘴狗贸易有限公司",    ContactName = "陈大爷",    Qty = 425.12f,    UP = 1000.55M,    Date = new(2020, 10, 27)   };

假如我要在变量 od 上做 switch,看看,就这样:

switch.........

版权声明
本文为[程序猿欧文]所创,转载请带上原文链接,感谢
https://my.oschina.net/mikeowen/blog/4710281