首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 匿名型別在 CLR 層面的實現機制深度解析

     編輯:關於C#

語言特性 vs 執行階段

匿名型別是 **C# 編譯器** 的語法糖,CLR (Common Language Runtime) 本身**不感知**匿名型別概念,只見到普通的泛型類別。

編譯器生成的型別結構


var p1 = new { Name = "IORI", Age = 27 };

編譯器產生 (IL 反編譯):


.class private auto ansi sealed '<>f__AnonymousType0`2'<<Name>j__TPar, <Age>j__TPar>
       extends [mscorlib]System.Object
{
    .field private initonly <Name>j__TPar '<Name>i__Field'
    .field private initonly <Age>j__TPar '<Age>i__Field'

    .method public hidebysig specialname rtspecialname 
        instance void .ctor(!0 Name, !1 Age) cil managed { ... }

    .method public hidebysig virtual instance bool Equals(object value) { ... }
    .method public hidebysig virtual instance int32 GetHashCode() { ... }
    .method public hidebysig virtual instance string ToString() { ... }

    .property instance !0 Name() { .get instance !0 '<>f__AnonymousType0`2'::get_Name() }
    .property instance !1 Age() { .get instance !1 '<>f__AnonymousType0`2'::get_Age() }
}

關鍵特性總結

特性說明
繼承隱含繼承 System.Object
密封sealed,不可繼承
不可變所有屬性 initonly (readonly),建構函式一次設定
泛型依屬性名稱、型別、順序產生泛型參數
Equality逐屬性 EqualityComparer<T>.Default.Equals 比較
GetHashCode組合各屬性 HashCode
ToString格式 { Name = IORI, Age = 27 }

同一組件內的型別共享


var p1 = new { Name = "A", Age = 1 };
var p2 = new { Name = "A", Age = 1 };
var p3 = new { Name = "B", Age = 1 };
var p4 = new { Age = 1, Name = "A" }; // 順序不同!

Console.WriteLine(p1.GetType() == p2.GetType()); // True  (同名稱、型別、順序)
Console.WriteLine(p1.GetType() == p3.GetType()); // True  (值不同不影響型別)
Console.WriteLine(p1.GetType() == p4.GetType()); // False (屬性順序不同 → 不同型別)

跨組件界限

  • 匿名型別為 internal,**無法跨組件邊界傳遞** (無法作為 public API 參數/回傳值)。
  • 需跨組件請定義具名 record、class 或 struct。

常見用法與限制

C# 9+ Record 型別:更好的替代方案


// 具名、可跨組件、支援 with-expression、預設不可變
public record Person(string Name, int Age);

// 使用
var p = new Person("IORI", 27);
var p2 = p with { Age = 28 }; // 非破壞性更新

總結

匿名型別是編譯器為「臨時資料組合」生成的 sealed、readonly、泛型類別,提供結構化相等比較與良好除錯體驗。**僅限區域使用**,跨邊界、長壽命、需序列化合約穩定時,請改用 record 或具名型別。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景適用性備註
LINQ 投影 select new { ... }✅ 最佳區域變數、立即消費
區域變數暫存多欄位✅ 適合避免建立 DTO 類別
方法回傳值❌ 避免回傳 object 需反射,失去型別安全
非同步流程傳遞❌ 避免跨 await 邊界需捕獲至狀態機,易造成記憶體洩漏
序列化 (JSON)✅ 支援Newtonsoft.Json / System.Text.Json 皆可正確序列化