<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          C# 中的 is 真的是越來越強(qiáng)大,越來越語義化

          共 3974字,需瀏覽 8分鐘

           ·

          2020-10-02 18:10

          一:背景

          1. 講故事

          最近發(fā)現(xiàn) C#7 之后的 is 是越來越看不懂了,乍一看花里胡哨的,不過當(dāng)我靜下心來仔細(xì)研讀,發(fā)現(xiàn)這 is 是越來越短小精悍,而且還特別語義化,那怎是一個(gè)爽字了得?,這一篇就和大家簡(jiǎn)單聊一聊。

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

          1. 類型兼容性檢測(cè)

          相信學(xué)過 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ù)的過程中用到 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 的功能,那就??了,我覺得這個(gè)急需增強(qiáng)。

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

          也終于在 C#7 之后對(duì) is 進(jìn)行了翻天覆地的語法糖改造,導(dǎo)致你初看已經(jīng)不明白啦???,下面我就一一舉例來說明吧。

          1. is 和 復(fù)雜類型/簡(jiǎn)單類型 的結(jié)合

          現(xiàn)在就來看一下怎么用新is 解決剛才兩次轉(zhuǎ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)證是否如我所說,用反編譯工具看看。

          • ILSpy 反編譯
          • DnSpy 反編譯

          可以看到,在實(shí)操中,編譯器都用 as 進(jìn)行了還原,不過從代碼流暢性來看,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");
          ????????????}

          這么語義化的寫法在C#中看到是不是有點(diǎn)不習(xí)慣,那為啥在 sql 中就習(xí)以為常呢?其實(shí)反編譯過來也沒啥,就是一個(gè) == 判斷,如下代碼:

          3. is 和 and ,or 的結(jié)合

          現(xiàn)在大家都看到了 is 通常是放在 if 語句中,既然在 if 語句中,那肯定有很多的邏輯判斷,這就需要結(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é)合起來就更??了,可以實(shí)現(xiàn)在 if 判斷的過程中生成臨時(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í)變量的,如果還沒有領(lǐng)會(huì)到精粹,沒關(guān)系,我舉一個(gè)項(xiàng)目中的例子吧。。。

          我們公司是搞衣物洗滌自動(dòng)化,也需要對(duì)線下 傳輸線上的衣服進(jìn)行自動(dòng)化上掛,取走和衣物組合搭配,舉個(gè)例子:找到 剛好掛了一件褲子L && 一件上衣L && 總衣服個(gè)數(shù)=2 的 掛孔號(hào),要是還沒聽懂就算了,直接上代碼說話。


          class?Program
          ????{
          ????????static?void?Main(string[]?args)
          ????????{
          ????????????var?slotList?=?new?List()
          ????????????{
          ????????????????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é)

          我覺得 is 的功能增強(qiáng)早就該出現(xiàn)了,現(xiàn)在終于搞定了,越來越人性化,鍵盤敲擊次數(shù)越來越少,頭發(fā)也不落了,甚至又開始第二春了,總的來說還是那句話,C# 大法??。

          瀏覽 33
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美www网站免费 | 欧美一级黄色电影免费看 | 一区二区三区小视频 | 在线电影无码 | 中字三级视频网站在线观看 |