匿名類型提供無需定義具名類別即可建立強型別物件的能力,廣泛用於 LINQ 投影、臨時資料封裝。本文系統整理建立語法、編譯器生成機制、型別身分規則、屬性存取與跨方法傳遞限制。
// 基本建立
var person = new { Name = "oec2003", Age = 100 };
// 屬性投射(從現有物件)
class User { public string Name { get; set; } public int Age { get; set; } }
User u = new User { Name = "Tom", Age = 25 };
var projected = new { u.Name, u.Age }; // 屬性名自動推斷
var:必要,因匿名類型無名稱new { ... }:物件初始化器語法,屬性名與值由編譯器推斷型別get)編譯器產生內部類別(如 <>f__AnonymousType0<string, int>),包含:
initonly)Equals/GetHashCode/ToString同一組件內,下列條件全部滿足時重用型別:
var a = new { Name = "A", Age = 10 };
var b = new { Name = "B", Age = 20 }; // 同型別
var c = new { Age = 10, Name = "A" }; // 不同型別(順序不同)
var d = new { Name = "A", Age = 10L }; // 不同型別(long vs int)
a = b; // 合法
// a = c; // 編譯錯誤
var person = new { Name = "Tom", Age = 25 };
string name = person.Name; // 強型別存取,IntelliSense 完整支援
int age = person.Age;
// person.Name = "Jerry"; // 編譯錯誤:屬性唯讀
匿名類型無法作為方法參數型別或回傳型別宣告(因無名稱)。傳遞方式:
| 方式 | 優點 | 缺點 |
|---|---|---|
object | 簡單 | 失去強型別,需反射或 dynamic 存取 |
dynamic | 語法自然 | 失去編譯期檢查,執行期才報錯 |
| 泛型方法 + 樣本實例 | 保持強型別 | 結構變更易崩潰,屬 Hack 技巧 |
| 改用 Tuple/record/具名類別 | 型別安全、跨組件可用 | 需額外定義 |
select new { ... } 投影