在反射與動態程式設計中,取得泛型型別的 Type 物件是基礎操作。本文詳細說明開放型別與封閉建構型別的差異、typeof 與 GetType() 的正確用法,以及常見錯誤與解決方案。
GenericClass<T> — 型別參數未指定,無法建立實例,沒有 Type 物件GenericClass<int>、GenericClass<string> — 型別參數已具體化,擁有獨立 Type 物件Type t = typeof(Simple); // 直接使用類別名稱
// 正確:提供具體型別引數
Type gtInt = typeof(GenericClass<int>);
Type gtBool = typeof(GenericClass<bool>);
Type gtString = typeof(GenericClass<string>);
// 錯誤:不提供型別引數
// Type gt = typeof(GenericClass); // CS0305: 型別引數計數錯誤
實例方法,適用於一般類別與泛型類別實例:
// 一般類別
Simple s = new Simple();
Type t1 = typeof(Simple);
Type t2 = s.GetType(); // 相同
// 泛型類別實例
GenericClass<int> gci = new GenericClass<int>();
Type gt1 = typeof(GenericClass<int>);
Type gt2 = gci.GetType(); // 相同,回傳 GenericClass`1[System.Int32]
// 編譯錯誤 CS0305
Type gt = typeof(GenericClass); // 缺少 1 個型別引數
// 正確做法:必須指定型別參數
Type gtInt = typeof(GenericClass<int>);
| 情境 | 正確用法 |
|---|---|
| 編譯期已知型別 | typeof(SomeType) 或 typeof(Generic<Int>) |
| 執行期從實例取得 | instance.GetType() |
| 執行期從字串取得 | Type.GetType("Namespace.Generic`1[[System.Int32]]") |
Type closedType = typeof(List<int>);
// 取得開放型別定義
Type openType = closedType.GetGenericTypeDefinition(); // List`1
// 取得型別引數
Type[] args = closedType.GetGenericArguments(); // [System.Int32]
Console.WriteLine(openType); // System.Collections.Generic.List`1[T]
Console.WriteLine(args[0]); // System.Int32
typeof(IRepository<>) 開放型別,解析時建構 typeof(Repository<Customer>)Activator.CreateInstance(typeof(GenericClass<int>))type.GetInterfaces() 檢查泛型介面實作泛型型別的 Type 物件只存在於「封閉建構型別」(已指定型別參數)。typeof 需在編譯期提供型別引數;GetType() 從實例取得。理解開放/封閉型別區別,是正確使用泛型反射的關鍵。