1. 程式人生 > 程式設計 >C# 中的 is 真的是越來越強大越來越語義化(推薦)

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;}
  }

C# 中的 is 真的是越來越強大越來越語義化(推薦)

從這個例子可以看到, 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}");
   }

C# 中的 is 真的是越來越強大越來越語義化(推薦)

這就導致很多場景下,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}");
   }

C# 中的 is 真的是越來越強大越來越語義化(推薦)

這段程式碼表面意思是:先用 is 檢測 slot 是否為 Slot 型別,如果是就賦值給 Slot 型別的 query 變數,哈哈,有點意思吧,為了驗證是否如我所說,用反編譯工具看看。

ILSpy 反編譯

C# 中的 is 真的是越來越強大越來越語義化(推薦)

DnSpy 反編譯

C# 中的 is 真的是越來越強大越來越語義化(推薦)

可以看到,在實操中,編譯器都用 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 中就習以為常呢? 其實反編譯過來也沒啥,就是一個 == 判斷,如下程式碼:

C# 中的 is 真的是越來越強大越來越語義化(推薦)

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 功能");
   }

C# 中的 is 真的是越來越強大越來越語義化(推薦)

可以看到最後的: e is not null and not "" 其實等價於 !string.IsNullOrEmpty,是不是有點意思哈。

這裡有一點要提醒的是,上面的 e 在編譯器層面都是 object 型別,如果你想在 編譯器層面使用 int 運作,還是用 例子1 的方式轉換一下哈,如下圖所示:

C# 中的 is 真的是越來越強大越來越語義化(推薦)

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" },ClothesID=11,ClothesName="皮帶",SizeName= "X" },new Slot() {SlotID=2,ClothesID=30,ClothesID=40,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; }
  }
 }

C# 中的 is 真的是越來越強大越來越語義化(推薦)

重點在於上面程式碼的 m.Where(n => n.SizeName == "L").ToList() is var clothesList ,這裡的 clothesList 就是臨時變數,它存放了所有 尺寸L 的衣物,後續的檢索都是基於這個 clothesList,是不是大大提高了檢索速度~~~

四:總結

我覺得 is 的功能增強早就該出現了,現在終於搞定了,越來越人性化,鍵盤敲擊次數越來越少,頭髮也不落了,甚至又開始第二春了,總的來說還是那句話,C# 大法🐂👃。

更多高質量乾貨:參見我的 GitHub: dotnetfly

到此這篇關於C# 中的 is 真的是越來越強大越來越語義化的文章就介紹到這了,更多相關C# 中 is 內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!