最近发现 C#7 以后的 is 是愈来愈看不懂了,乍一看花里胡哨的,不过当我静下心来仔细研读,发现这 is 是愈来愈短小精悍,并且还特别语义化,那怎是一个爽字了得😄,这一篇就和你们简单聊一聊。git
相信学过 C# 的朋友都会知道 is 是干吗的,并且还常常和 as 一块儿比较,前者通常作兼容性检测,后者通常作兼容性转换,这里我就举个例子吧:github
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 都是类型兼容的,很是简单。sql
### 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 尝试性转换将两步合为一步走呢? 修改代码以下:spa
var query = slot as Slot; if (query != null) { Console.WriteLine($"slot is {nameof(Slot)}, ClothesName={query.ClothesName}"); }
这就致使不少场景下,is 都被 as 替代了,搞的 is 成了一个空架子,若是 is 能合并 as 的功能,那就🐂👃了,我以为这个急需加强。3d
也终于在 C#7 以后对 is 进行了翻天覆地的语法糖改造,致使你初看已经不明白啦😄😄😄,下面我就一一举例来讲明吧。code
如今就来看一下怎么用新is 解决刚才两次转换的问题,以下代码:blog
object slot = new Slot() { ClothesName = "上衣" }; if(slot is Slot query) { Console.WriteLine($"slot is {nameof(Slot)}, ClothesName={query.ClothesName}"); }
这段代码表面意思是:先用 is 检测 slot 是否为 Slot 类型,若是是就赋值给 Slot 类型的 query 变量,哈哈,有点意思吧,为了验证是否如我所说,用反编译工具看看。ip
能够看到,在实操中,编译器都用 as 进行了还原,不过从代码流畅性来看,ILSpy更🐂👃一点。
除了和类实例比较以外,还能够和 int,string,tuple ...进行比较, 代码以下:
object e = 150; //字符串比较 if (e is "hello") { } //整形比较 if (e is 10) { } //tuple 比较 if (e is (10, 20)) { }
你们在写 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 中就习觉得常呢? 其实反编译过来也没啥,就是一个 == 判断,以下代码:
如今你们都看到了 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 的方式转换一下哈,以下图所示:
当 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# 大法🐂👃。
更多高质量干货:参见个人 GitHub: dotnetfly