[廚餘回收] 中了一個 C# 模式比對(Pattern Matching)var 的陷阱

  • 1469
  • 0
  • C#
  • 2019-10-07

C# 從 7.0 開始加入了模式比對(Pattern Matching),最大的改變是將 switch 從常數比對中解放,讓 switch 可以比對運算式,到了 C# 8.0 更猛了,微軟弄了一個遞迴模式比對(Recursive Pattern Matching),大括號 "{}" 及小括號 "()" 寫到你不要不要的,但是模式比對裡面藏了一個 var 的陷阱,我就踩中了。

C# 8.0 的遞迴模式比對中有一個 Property Pattern Matching 的語法,我們直接看程式碼比較快,假設我的 Employee 集合中有 4 筆資料,透過 Filter() 方法可以回傳 Employee 的 Id 跟 Name,而且 Property Pattern Matching 預設會幫我們把 Id 跟 Name 為 Null 的資料給過濾掉。

按照我集合中的資料,過濾出來的資料筆數只會有 2 筆。

我利用 Property Pattern Matching 預設會過濾掉 Null 值的特性,想說把 Address 為 Null 的也給過濾掉,於是我加了一個條件。

預期應該只會有 1 筆資料,結果跑出來還是 2 筆。

但是如果不用 var 改用明確型別 Address,它跑出來的結果就符合預期。

正當我百思不得其解還以為找到微軟的 Bug 之際,我搜尋到這份原廠文件,當中的規則二:

var 宣告不具有其他類型模式運算式所包含的 Null 檢查。 這表示變數可能是 null,並且在這種情況下需要 null 檢查。

真相大了個白「這不是 Bug,是 Feature。」,所以針對我剛剛使用 var 的情境,我必須額外做 Null 判斷(或改用明確型別),結果就符合預期了。

另外 C# 8.0 的 Property Pattern Matching 允許我們直接用 { } 來宣告輸出參數的型別,編譯器會幫我們做型別推斷,下面程式碼的結果等於使用明確型別,一樣會做 Null 檢查。

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學