泛型與反射:為什麼需要?
泛型:一份程式碼,適用所有型別
沒有泛型的世界
// 要為每種型別寫一個方法?
int MaxInt(int a, int b) => a > b ? a : b;
double MaxDouble(double a, double b) => a > b ? a : b;
string MaxString(string a, string b) => a.CompareTo(b) > 0 ? a : b;
// 無限重複...
// 或者用 object?
object Max(object a, object b) { ... }
// 問題:沒有型別安全、需要 Boxing、呼叫端要強制轉型
泛型解決方案
T Max<T>(T a, T b) where T : IComparable<T> {
return a.CompareTo(b) > 0 ? a : b;
}
// 一個方法適用所有可比較的型別
Max(5, 10); // T = int
Max(3.14, 2.72); // T = double
Max("abc", "xyz"); // T = string
泛型的好處
| 好處 | 說明 |
|---|---|
| 型別安全 | 編譯時期檢查,不用強制轉型 |
| 效能 | 值型別不需要 Boxing |
| 重用 | 一份程式碼適用所有型別 |
| 約束 | where T : IComparable 限制能用的型別 |
反射:在執行時期檢查和操作型別
什麼時候需要反射?
// 1. 框架(ASP.NET、EF Core 大量使用反射)
// ASP.NET 怎麼知道你的 Controller 有哪些 Action?→ 反射掃描
// EF Core 怎麼知道你的 Entity 有哪些屬性?→ 反射讀取
// 2. 序列化
// JSON.Serialize 怎麼知道物件有哪些屬性?→ 反射
// 3. 外掛系統
// 動態載入 DLL,建立不知道型別的物件
反射的代價
反射比直接呼叫慢 10-100 倍
→ 不要在迴圈裡用反射
→ 框架會快取反射結果來減少開銷
→ 現在有 Source Generator 可以在編譯時期產生程式碼取代反射
原則:應用程式碼很少需要直接用反射。如果你在寫業務邏輯時用到反射,通常代表設計可以改進。