C# 中的 is 真的是越来越强大,越来越语义化

一:背景

1. 讲故事

最近发现 C#7 之后的 is 是越来越看不懂了,乍一看花里胡哨的,不过当我静下心来仔细研读,发现这 is 是越来越短小精悍,而且还特别语义化,那怎是一个爽字了得????,这一篇就和大家简单聊一聊。

二:C#7 之前的 is 如何使用

1. 类型兼容性检测

相信学过 C# 的朋友都会知道 is 是干嘛的,而且还经常和 as 一起比较,前者一般做兼容性检测,后者一般做兼容性转换,这里我就举个例子吧:

static void Main(string[] args){object slot = new Slot() { ClothesName = "上衣" };if (slot is Slot){Console.WriteLine($"slot is {nameof(Slot)}");}if (slot is IComparable){Console.WriteLine($"slot is {nameof(IComparable)}");}}public class Slot : IComparable{public string ClothesName { get; set; }public int CompareTo(object obj) {return 0;}}

从这个例子可以看到, object 类型的 slot 和 Slot, IComparable 都是类型兼容的,非常简单。

2. 遗憾的地方

然而在实际编码中,我相信有很多朋友都会在后续的过程中用到 slot 实例,而上面的这个例子,即使我用 is 检测到了是 Slot 类型,最后我还是要 将 object slot 强转成 Slot类型,做了一次检测,又做了一个强转,这就很奇葩了,如下代码:

if (slot is Slot){var query = (Slot)slot;Console.WriteLine($"slot is {nameof(Slot)}, ClothesName={query.ClothesName}");}

除非有毛病才写这样的代码,干嘛不直接用 as 尝试性转换将两步合为一步走呢?修改代码如下:

var query = slot as Slot;if (query != null){Console.WriteLine($"slot is {nameof(Slot)}, ClothesName={query.ClothesName}");}

这就导致很多场景下,is 都被 as 替代了,搞的 is 成了一个空架子,如果 is 能合并 as 的功能,那就????????了,我觉得这个急需增强。

三:C#7 之后的 is 如何使用

也终于在 C#7 之后对 is 进行了翻天覆地的语法糖改造,导致你初看已经不明白啦????????????,下面我就一一举例来说明吧。

1. is 和 复杂类型/简单类型 的结合

现在就来看一下怎么用新is 解决刚才两次转换的问题,如下代码:

object slot = new Slot() { ClothesName = "上衣" };if(slot is Slot query){Console.WriteLine($"slot is {nameof(Slot)}, ClothesName={query.ClothesName}");}

这段代码表面意思是:先用 is 检测 slot 是否为 Slot 类型,如果是就赋值给 Slot 类型的 query 变量,哈哈,有点意思吧,为了验证是否如我所说,用反编译工具看看。

  • ILSpy 反编译

  • DnSpy 反编译

可以看到,在实操中,编译器都用 as 进行了还原,不过从代码流畅性来看,ILSpy更????????一点。

除了和类实例比较之外,还可以和 int,string,tuple ...进行比较, 代码如下:

object e = 150;//字符串比较if (e is "hello") { }//整形比较if (e is 10) { }//tuple 比较if (e is (10, 20)) { }

2. is 和 null 的结合

大家在写 sql 的时候判断某一个字段是否为 null,通常都会这样写:username is null 或者 username is not null ,哈哈,这种写法也被引入到 C# 中了,有意思吧,上代码:

object e = 150;if (e is null){Console.WriteLine("e is null");}if (e is not null){Console.WriteLine("e is not null");}

这么语义化的写法在C#中看到是不是有点不习惯,那为啥在 sql 中就习以为常呢?其实反编译过来也没啥,就是一个 == 判断,如下代码:

3. is 和 and ,or 的结合

现在大家都看到了 is 通常是放在 if 语句中,既然在 if 语句中,那肯定有很多的逻辑判断,这就需要结合 and,or 构建非常复杂的逻辑关系,不要眼花哦。

object e = 150;if (e is >= 100 and <= 200){Console.WriteLine($"e={e} 果然 大于 100 并且 小于 200");}if (e is 100 or 150 or 200){Console.WriteLine($"e={e} 是在 100,150,200 三个数字中");}if (e is not null and not ""){Console.WriteLine($"e={e},模拟 !string.IsNullOrEmpty 功能");}

可以看到最后的: e is not null and not "" 其实等价于 !string.IsNullOrEmpty, 是不是有点意思哈。

这里有一点要提醒的是,上面的 e 在编译器层面都是 object 类型,如果你想在 编译器层面使用 int 运作,还是用 例子1 的方式转换一下哈,如下图所示:

4. is 和 var 的结合

当 is 和 var 结合起来就更????????了,可以实现在 if 判断的过程中生成临时变量,如下代码:

int e = 150;if (e is var i && i >= 100 && i <= 200){Console.WriteLine($"e={i} 果然 大于 100 并且 小于 200");}

上面代码中的 i 就是一个临时变量,后面做的一切业务逻辑都是基于 i 这个临时变量的,如果还没有领会到精粹,没关系,我举一个项目中的例子吧。。。

我们公司是搞衣物洗涤自动化,也需要对线下 传输线上的衣服进行自动化上挂,取走和衣物组合搭配,举个例子:找到 刚好挂了一件裤子L && 一件上衣L && 总衣服个数=2 的 挂孔号,要是还没听懂就算了,直接上代码说话。


class Program{static void Main(string[] args){var slotList = new List<Slot>(){new Slot()  {SlotID=1, ClothesID=10,ClothesName="上衣", SizeName= "L" },new Slot()  {SlotID=1, ClothesID=20,ClothesName="裤子", SizeName= "M" },new Slot()  {SlotID=1, ClothesID=11,ClothesName="皮带", SizeName= "X" },new Slot()  {SlotID=2, ClothesID=30,ClothesName="上衣", SizeName= "L" },new Slot()  {SlotID=2, ClothesID=40,ClothesName="裤子", SizeName= "L" }};//找到 刚好挂了一件裤子L & 一件上衣L  & 总衣服个数=2  的 挂孔号var query = slotList.GroupBy(m => m.SlotID).Where(m =>m.Where(n => n.SizeName == "L").ToList() is var clothesList &&clothesList.Count(k => k.ClothesName == "裤子") is 1 &&clothesList.Count(k => k.ClothesName == "上衣") is 1 &&m.Key == 2).ToDictionary(k => k.Key, v => v.ToList());}public class Slot{public int SlotID { get; set; }public int ClothesID { get; set; }public string ClothesName { get; set; }public string SizeName { get; set; }}}

重点在于上面代码的  m.Where(n => n.SizeName == "L").ToList() is var clothesList,这里的 clothesList 就是临时变量,它存放了所有 尺寸L 的衣物,后续的检索都是基于这个 clothesList,是不是大大提高了检索速度~~~

四:总结

我觉得 is 的功能增强早就该出现了,现在终于搞定了,越来越人性化,键盘敲击次数越来越少,头发也不落了,甚至又开始第二春了,总的来说还是那句话,C# 大法????????。

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

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

相关文章

leetcode209. 长度最小的子数组(滑动窗口)

一:题目 二:上码 class Solution { public:/**思路:1.滑动窗口解法1>:确定窗口内是什么2>:确定窗口的起始位置3>:确定窗口的终止位置2.窗口:也就是我们的求的连续字符串的和3.窗口的起始位置: 窗口的起始位置最先是我们数组的起始位置,当窗口内连续数组的和大于targe…

开源特训营 - Lesson 4 - 如何运营社区

编辑&#xff1a;李明康责编&#xff1a;袁睿斌作者&#xff1a;课程助教 - 苏斌主讲教师&#xff1a;庄表伟&#xff08;开源社理事长&#xff09;、赵生宇&#xff08;同济大学&#xff09;本次课程的主题为《如何运营社区》&#xff0c;主讲者为开源社的理事长庄表伟老师和来…

leetcode904. 水果成篮(滑动窗口)

一:题目 二:上码 class Solution { public:/**思路:滑动窗口1.滑动窗口为我们 两个品种水果的个数2.滑动窗口的起始位置为数组的起始位置,当遇见一个新的水果种类的时候,这时候就需要移动我们的起始位置这里移动起始位置是要注意的,我们需要移动起始到我们的窗口中 完全没有 这…

拥抱.NET 5,从自研微服务框架开始

“ 2016年发布了.NET Core第一个正式版本&#xff0c;而.NET5也将在下个月就正式来临了&#xff0c;技术日新月异&#xff0c;也有点让人应接不暇。在框架设计上&#xff0c;.NET Framework的全家桶理念&#xff0c;培养了一大批的CRUD&#xff0c;而.NET Core转变成了按需使用…

leetcode周赛第一题6037. 按奇偶性交换后的最大数字(冒泡法)

一:题目 二:上码 class Solution { public:int largestInteger(int num) {string str to_string(num);for (int i 0; i < str.size()-1; i) {for (int j i1; j < str.size(); j) {int num1 str[j]-0;int num2 str[i]-0;if (num1%2 num2%2) {//这里我们控制的是奇数…

从零开始打造专属钉钉机器人

一、前言废话不多的实现简单的钉钉机器人。我们分为下面几个步骤来逐步讲解。1.钉钉机器人的类型2.如何打造一个最最简单的钉钉机器人二、钉钉机器人的类型常用的钉钉机器人有两种&#xff0c;1、通知类型的机器人&#xff1a;适合在群内进行一些通知&#xff0c;推荐消息等内容…

Azure 内容审查器之文本审查

内容审查器Azure 内容审查器也是一项认知服务。它支持对文本、图形、视频进行内容审核。可以过滤出某些不健康的内容&#xff0c;关键词。使你的网站内容符合当地的法律法规&#xff0c;提供更好的用户体验。文本内容审核其中文本内容的审核应用比较广泛。比如在审核游戏中的群…

java并发之CAS

文章目录1:何为CAS2:CAS图示3:CAS和Volatile的关系4:为何CAS效率更高一些5:CAS的特点7:受保护得共享数据类型(1):原子基本数据类型(2):原子引用数据类型7:ABA问题(1):什么是ABA(2):如何解决呢&#xff1f;1:何为CAS CAS(Compare And Swap)&#xff0c;即比较并交换。是解决多线…

快速了解 ASP.NET Core Blazor

最近在几个微信 .NET 交流群里大家讨论比较频繁的话题就是这几天自己的面试经历。面试官&#xff1a;“你刚说你喜欢研究新技术&#xff0c;那你有了解过 Blazor 吗&#xff1f;”作为一位专注于 .NET 开发的软件工程师&#xff0c;你好意思说你对 Blazor 一点也不解吗&#xf…

ASP.NET Core集成Nacos配置中心之适配多格式配置

前言 默认情况下&#xff0c;用nacos-sdk-csharp集成ASP.NET Core的配置系统&#xff0c;是基于JSON格式的数据。随着业务系统的多样化&#xff0c;可能用的配置格式也是各有千秋的。有的会用yaml/yml&#xff0c;有的会用ini&#xff0c;有的会用xml&#xff0c;等等。那么如果…

Git的使用(快速入门)

文章目录[TOC]一:将本地的项目提交到Git上二:GIt的基本操作1:建立一个本地仓库(1):类别(2):创建全新的仓库(3):克隆远程仓库2:查看文件的状态3:在桌面上的文件提交到远程仓库4:在idea中的文件提交到远程仓库5:分支(1):何为分支(2):常用命令(3)注意6:解决合并冲突(1):问题展示(2…

为什么这么忙,还依然做不好事情?

一直都很喜欢《重来》系列&#xff0c;最近出了《重来3&#xff1a;跳出疯狂的忙碌》&#xff0c;第一时间在微信读书中阅读了&#xff0c;让我们印象比较深刻的就是「冷静」和「效率」&#xff0c;本文主要说说效率的问题。书的作者是贾森弗里德&#xff08;Jason Fried&#…

开源特训营 - Lesson 6 - 如何提交一个合格的PR

编辑&#xff1a;李明康责编&#xff1a;袁睿斌作者&#xff1a;课程助教 - 苏斌主讲教师&#xff1a;张齐勋&#xff08;北京大学&#xff09;、赵生宇&#xff08;同济大学&#xff09;本次课程的主题为《如何提交一个合格的PR》&#xff0c;主讲者为来自北京大学的张齐勋老师…

改进程架构,Edge优化浏览器内存问题

微软 Edge 团队称&#xff0c;“今天的浏览器更像是操作系统&#xff0c;而不是文档查看器。用户正在浏览器中执行越来越多的任务&#xff0c;而在桌面应用程序中执行的任务越来越少。与此同时&#xff0c;每个网页、Web 应用程序和扩展程序都在使用内存&#xff0c;这也会使用…

中芯国际第二代FinFET工艺有望与2020年底试产

媒体报道&#xff0c;第一代FinFET 14纳米已于2019年四季度量产&#xff1b;第二代FinFET N1已进入客户导入阶段&#xff0c;可望于2020年底小批量试产。梁孟松披露&#xff0c;中芯国际的下一代N1工艺和14nm相比&#xff0c;性能提升了20%&#xff0c;功耗降低了57%&#xff0…

gRPC-微服务间通信实践

微服务间通信常见的两种方式由于微服务架构慢慢被更多人使用后&#xff0c;迎面而来的问题是如何做好微服务间通信的方案。我们先分析下目前最常用的两种服务间通信方案。gRPC&#xff08;rpc远程调用&#xff09;场景&#xff1a;A服务主动发起请求到B服务&#xff0c;同步方式…

移动 Azure 资源后如何快速修复 Dashboard

点击上方蓝字关注“汪宇杰博客”导语Azure 用户经常因为不够有钱&#xff0c;需要把资源移动到另一个资源组或订阅中。移动完成后&#xff0c;会导致资源对应的 Dashboard 失效。通常&#xff0c;我们都需要从 Dashboard 上将找不到的资源删除&#xff0c;并逐个重建。有没有快…

八大排序算法之插入排序

一:直接插入排序 1:思想 首先选择一个哨兵,我们默认将第一个数作为哨兵,随着循环的进行,我们一直将我们待插入数的前一个数作为哨兵然后就是插入的数与哨兵比较&#xff0c;比哨兵小的话&#xff0c;就将哨兵后移&#xff0c;然后再与哨兵前面的数进行比较&#xff0c;直到遇…

跟我一起学Redis之五种基本类型及其应用场景举例(干了6个小时)

前言来啦&#xff0c;老弟&#xff1f;来啦&#xff0c;上一篇就当唠唠嗑&#xff0c;接下来就开始进行实操撸命令&#xff0c;计划是先整体单纯说说Redis的各种用法和应用&#xff0c;最后再结合代码归纳总结。Redis默认有16个数据库(编号为0~15)&#xff0c;默认使用第0个&am…

leetcode周赛6070. 计算字符串的数字和

一:题目 二:上码 class Solution { public:/**思路:1.设置一个while循环&#xff0c;循环的条件是s.length<k2.while里面进行 1>:将字符串按k个进行拆分成个单个字符&#xff0c;并将其转换成数字,然后计算将计算结果再组成字符串 */string digitSum(string s, int k) {…