前情提要
我以前是很排斥變更Unity 版本的,一來要重新下載,二來重跑編譯不知道會不會出甚麼大事,尤其跨版更新那更是刺激,但隨著Unity 逐漸穩定,現在更新反而利大於弊,這篇就來說說近幾版C# 的語法糖與功能,順便水一篇。
這篇主要講的是 C# 9.0 ! (Unity 2021 later )
new()
這算是最常用到的,對於超級懶人的我來說。直接上程式碼:
對於已知類型的情況下,直接打上 new() 來使用建構式建立對象。
這讓泛型的宣告變得簡短很多:
沒錯,方法的回傳值也有明確定義,所以也能使用這個語法糖。
模式匹配
這部分是最近在學 Rust 才注意到的功能,C#9.0 也新增了不少模式匹配的關鍵字,可以用更簡潔的方式把程式碼完成。先看一個簡單的例子:
這是一個簡單的方法,判斷輸入的分數應給出甚麼評語,這邊用到了 and 關鍵字,這正是奇妙的地方。
C#9.0 新增了 is / or / and / not 關鍵字 來強化模式匹配的撰寫彈性,但由於麻煩的運算順序,使用時最好要加上括號來確保條件的正確性,而且 不推薦與邏輯運算子混用 。
運作順序如下:
not 👉 關係運算子 👉 and 👉 or
另外元組(Tuple)也能用解構的方式進行模式匹配:
Record
最後來說說 Record 這個特殊的類型。
先來看這段程式碼:
如果稍微熟悉 class 與 struct 特性的同學應該不難理解這個範例:
- class 為 參考 物件,針對 記憶體位址 進行比對
- class 指定時複製記憶體位址
- struct 為 實值 物件,針對 值 進行比對
- struct 指定時複製整個物件
而要介紹的 Record 正介於這兩者之間。上程式碼:
可以觀察到 Record 特性如下:
- record 為 參考 物件
- record 指定時複製記憶體位址
- record 針對 值 進行比對
宣告
1. 精簡宣告:
如上面範例的單行宣告,因為會自動產生解構子,是我最常使用的宣告方式,拿來取代使用元組的情況。
使用精簡宣告會讓其屬性自帶不可變性,與 readonly 有一樣的效果。
2. 自訂宣告:
不會自動產生建構子、解構子,但能自訂屬性是否可變,也能賦予預設值。
- L11: y 被宣告為唯讀,不能於建立時賦值
- L15:z 被宣告為 init-only ,只有在建立時能賦值
另外, Unity 在使用 Record 時可能會報錯
未定義 'System.Runtime.CompilerServices.IsExternalInit'
只需要在專案內新增一段程式碼:
就能消除錯誤了。
非破壞性變異
使用 with 關鍵字來初始化 record ,能夠在不破壞原物件的情況下更改內容。
範例中 pr2 使用了 pr 的值,同時變更了 x 。
繼承
record 提供了繼承能力,且能使用 abstract 修飾詞。
結語
這次講了比較多跟程式碼相關的內容,比較枯燥乏味,但妥善運用的確能讓程式碼的維護性提升。C#也算是經過時間淬鍊的語言了,近幾版很多更新都漸漸讓工程師的創造力不再被語言所侷限,儘管微軟有股臭銅味還是非常值得誇獎,讚嘆一聲我大微軟爸爸。