C# 中的 is 真的是越來(lái)越強(qiáng)大越來(lái)越語(yǔ)義化(推薦)
一:背景
1. 講故事
最近發(fā)現(xiàn) C#7 之后的 is 是越來(lái)越看不懂了,乍一看花里胡哨的,不過(guò)當(dāng)我靜下心來(lái)仔細(xì)研讀,發(fā)現(xiàn)這 is 是越來(lái)越短小精悍,而且還特別語(yǔ)義化,那怎是一個(gè)爽字了得😄,這一篇就和大家簡(jiǎn)單聊一聊。
二:C#7 之前的 is 如何使用
1. 類型兼容性檢測(cè)
相信學(xué)過(guò) C# 的朋友都會(huì)知道 is 是干嘛的,而且還經(jīng)常和 as 一起比較,前者一般做兼容性檢測(cè),后者一般做兼容性轉(zhuǎn)換,這里我就舉個(gè)例子吧:
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;}
}

從這個(gè)例子可以看到, object 類型的 slot 和 Slot, IComparable 都是類型兼容的,非常簡(jiǎn)單。
2. 遺憾的地方
然而在實(shí)際編碼中,我相信有很多朋友都會(huì)在后續(xù)的過(guò)程中用到 slot 實(shí)例,而上面的這個(gè)例子,即使我用 is 檢測(cè)到了是 Slot 類型,最后我還是要 將 object slot 強(qiáng)轉(zhuǎn)成 Slot類型,做了一次檢測(cè),又做了一個(gè)強(qiáng)轉(zhuǎn),這就很奇葩了,如下代碼:
if (slot is Slot)
{
var query = (Slot)slot;
Console.WriteLine($"slot is {nameof(Slot)}, ClothesName={query.ClothesName}");
}
除非有毛病才寫這樣的代碼,干嘛不直接用 as 嘗試性轉(zhuǎn)換將兩步合為一步走呢? 修改代碼如下:
var query = slot as Slot;
if (query != null)
{
Console.WriteLine($"slot is {nameof(Slot)}, ClothesName={query.ClothesName}");
}

這就導(dǎo)致很多場(chǎng)景下,is 都被 as 替代了,搞的 is 成了一個(gè)空架子,如果 is 能合并 as 的功能,那就🐂👃了,我覺(jué)得這個(gè)急需增強(qiáng)。
三:C#7 之后的 is 如何使用
也終于在 C#7 之后對(duì) is 進(jìn)行了翻天覆地的語(yǔ)法糖改造,導(dǎo)致你初看已經(jīng)不明白啦😄😄😄,下面我就一一舉例來(lái)說(shuō)明吧。
1. is 和 復(fù)雜類型/簡(jiǎn)單類型 的結(jié)合
現(xiàn)在就來(lái)看一下怎么用新is 解決剛才兩次轉(zhuǎn)換的問(wèn)題,如下代碼:
object slot = new Slot() { ClothesName = "上衣" };
if(slot is Slot query)
{
Console.WriteLine($"slot is {nameof(Slot)}, ClothesName={query.ClothesName}");
}

這段代碼表面意思是:先用 is 檢測(cè) slot 是否為 Slot 類型,如果是就賦值給 Slot 類型的 query 變量,哈哈,有點(diǎn)意思吧,為了驗(yàn)證是否如我所說(shuō),用反編譯工具看看。
ILSpy 反編譯

DnSpy 反編譯

可以看到,在實(shí)操中,編譯器都用 as 進(jìn)行了還原,不過(guò)從代碼流暢性來(lái)看,ILSpy更🐂👃一點(diǎn)。
除了和類實(shí)例比較之外,還可以和 int,string,tuple ...進(jìn)行比較, 代碼如下:
object e = 150;
//字符串比較
if (e is "hello") { }
//整形比較
if (e is 10) { }
//tuple 比較
if (e is (10, 20)) { }
2. is 和 null 的結(jié)合
大家在寫 sql 的時(shí)候判斷某一個(gè)字段是否為 null,通常都會(huì)這樣寫: 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");
}
這么語(yǔ)義化的寫法在C#中看到是不是有點(diǎn)不習(xí)慣,那為啥在 sql 中就習(xí)以為常呢? 其實(shí)反編譯過(guò)來(lái)也沒(méi)啥,就是一個(gè) == 判斷,如下代碼:

3. is 和 and ,or 的結(jié)合
現(xiàn)在大家都看到了 is 通常是放在 if 語(yǔ)句中,既然在 if 語(yǔ)句中,那肯定有很多的邏輯判斷,這就需要結(jié)合 and,or 構(gòu)建非常復(fù)雜的邏輯關(guān)系,不要眼花哦。
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 三個(gè)數(shù)字中");
}
if (e is not null and not "")
{
Console.WriteLine($"e={e},模擬 !string.IsNullOrEmpty 功能");
}

可以看到最后的: e is not null and not "" 其實(shí)等價(jià)于 !string.IsNullOrEmpty, 是不是有點(diǎn)意思哈。
這里有一點(diǎn)要提醒的是,上面的 e 在編譯器層面都是 object 類型,如果你想在 編譯器層面使用 int 運(yùn)作,還是用 例子1 的方式轉(zhuǎn)換一下哈,如下圖所示:

4. is 和 var 的結(jié)合
當(dāng) is 和 var 結(jié)合起來(lái)就更🐂👃了,可以實(shí)現(xiàn)在 if 判斷的過(guò)程中生成臨時(shí)變量,如下代碼:
int e = 150;
if (e is var i && i >= 100 && i <= 200)
{
Console.WriteLine($"e={i} 果然 大于 100 并且 小于 200");
}
上面代碼中的 i 就是一個(gè)臨時(shí)變量,后面做的一切業(yè)務(wù)邏輯都是基于 i 這個(gè)臨時(shí)變量的,如果還沒(méi)有領(lǐng)會(huì)到精粹,沒(méi)關(guān)系,我舉一個(gè)項(xiàng)目中的例子吧。。。
我們公司是搞衣物洗滌自動(dòng)化,也需要對(duì)線下 傳輸線上的衣服進(jìn)行自動(dòng)化上掛,取走和衣物組合搭配,舉個(gè)例子:找到 剛好掛了一件褲子L && 一件上衣L && 總衣服個(gè)數(shù)=2 的 掛孔號(hào),要是還沒(méi)聽(tīng)懂就算了,直接上代碼說(shuō)話。
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 & 總衣服個(gè)數(shù)=2 的 掛孔號(hào)
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; }
}
}

重點(diǎn)在于上面代碼的 m.Where(n => n.SizeName == "L").ToList() is var clothesList ,這里的 clothesList 就是臨時(shí)變量,它存放了所有 尺寸L 的衣物,后續(xù)的檢索都是基于這個(gè) clothesList,是不是大大提高了檢索速度~~~
四:總結(jié)
我覺(jué)得 is 的功能增強(qiáng)早就該出現(xiàn)了,現(xiàn)在終于搞定了,越來(lái)越人性化,鍵盤敲擊次數(shù)越來(lái)越少,頭發(fā)也不落了,甚至又開(kāi)始第二春了,總的來(lái)說(shuō)還是那句話,C# 大法🐂👃。
更多高質(zhì)量干貨:參見(jiàn)我的 GitHub: dotnetfly
到此這篇關(guān)于C# 中的 is 真的是越來(lái)越強(qiáng)大越來(lái)越語(yǔ)義化的文章就介紹到這了,更多相關(guān)C# 中 is 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#多線程學(xué)習(xí)之(二)操縱一個(gè)線程的方法
這篇文章主要介紹了C#多線程學(xué)習(xí)之操縱一個(gè)線程的方法,實(shí)例分析了C#中線程的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04
C#中is,as,using關(guān)鍵字的使用說(shuō)明
這篇文章主要介紹了C#中is,as,using關(guān)鍵字的使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
C#實(shí)現(xiàn)連接SQL Server2012數(shù)據(jù)庫(kù)并執(zhí)行SQL語(yǔ)句的方法
這篇文章主要介紹了C#實(shí)現(xiàn)連接SQL Server2012數(shù)據(jù)庫(kù)并執(zhí)行SQL語(yǔ)句的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了C#連接SQL Server2012數(shù)據(jù)庫(kù)并執(zhí)行查詢、插入等操作的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-10-10
通過(guò)實(shí)例解析c# yield關(guān)鍵字使用方法
這篇文章主要介紹了通過(guò)實(shí)例解析c# yield關(guān)鍵字使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
C#數(shù)組學(xué)習(xí)相關(guān)資料整理
最近開(kāi)始學(xué)習(xí)c#,并有幸接觸到了數(shù)組方便的操作,感覺(jué)確實(shí)不錯(cuò),這里簡(jiǎn)單的整理下c#相關(guān)的學(xué)習(xí)資料,方便大家學(xué)習(xí)2012-09-09
C#中LINQ的Select與SelectMany函數(shù)使用
這篇文章主要介紹了C#中LINQ的Select與SelectMany函數(shù)使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
C#對(duì)DataTable里數(shù)據(jù)排序的方法
在日常開(kāi)發(fā)過(guò)程中,有一個(gè)DataTable集合,里面有很多字段,現(xiàn)在要求針對(duì)某一列進(jìn)行排序,如果該列為數(shù)字的話,進(jìn)行ASC即可實(shí)現(xiàn),但是該字段類型為string,此時(shí)排序就有點(diǎn)不正確了2013-11-11
基于C#實(shí)現(xiàn)獲取Windows所有窗口句柄
在做錄屏或截屏操作時(shí),需要獲取當(dāng)前正在運(yùn)行中的桌面程序句柄,所以這篇文章主要為大家詳細(xì)介紹了如何使用C#實(shí)現(xiàn)獲取Windows所有窗口句柄,需要的可以參考下2023-12-12

