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

C# 3.0 匿名類型初體驗:編譯器自動生成類別

     編輯:關於C語言

什麼是匿名類型?

C# 3.0 引入的語法糖,允許無需預先定義類別,直接通過物件初始化器語法 new { Prop1 = val1, Prop2 = val2 } 創建唯讀、不可變的強類型物件。編譯器在編譯期自動生成對應的密封類別,包含屬性、Get/Set、建構函式、Equals/GetHashCode/ToString 重寫。

基礎語法

var p1 = new { Name = "A", Price = 3 };
Console.WriteLine($"Name = {p1.Name}, Price = {p1.Price}"); // 輸出 Name = A, Price = 3

編譯器幕後做了什麼?

等價於手寫:

class __Anonymous1
{
    private string _name;
    private int _price;
    public string Name { get => _name; set => _name = value; }
    public int Price { get => _price; set => _price = value; }
}
__Anonymous1 p1 = new __Anonymous1 { Name = "A", Price = 3 };

IL 驗證

ILDASM 顯示編譯器生成類別名稱如 <Projection>f__0,包含:

  • 私有欄位 _Name、_Price
  • 屬性 Name、Price (get/set)
  • 標註 ExtensionAttribute(雖非擴展方法,但同屬編譯器生成標記)

型別推論與重用規則

  • 同組件內:屬性名稱、順序、類型完全相同 → 重用同一匿名類型
  • 任何差異:屬性順序不同、名稱不同、類型不同、屬性數量不同 → 生成新類型

重用範例

var p1 = new { Name = "A", Price = 3 };
var p2 = new { Name = "A", Price = 3 }; // 同一類型
// p1.GetType() == p2.GetType() → true

不重用範例

var p1 = new { Name = "A", Price = 3 };
var p2 = new { Name = "A" }; // 缺少 Price
// 生成 <Projection>f__0 和 <Projection>f__1 兩個類型

核心特性

實戰應用場景

1. LINQ 投影

var result = customers
    .Where(c => c.City == "Taipei")
    .Select(c => new { c.Name, c.Email, OrderCount = c.Orders.Count });

2. 臨時資料傳遞 (區域)

var config = new { ConnectionString = "...", Timeout = 30, Retry = 3 };
// 僅在當前方法內使用

3. JSON 序列化匿名物件

var payload = new { action = "login", user = "admin", token = "xyz" };
string json = JsonSerializer.Serialize(payload); // System.Text.Json

限制與注意

  • 不可跨方法邊界傳遞(除非用 object/dynamic/反射)
  • 不可實作介面、繼承基類、定義方法
  • 屬性必須初始化,且初始化器不可為 null(除非明確類型)
  • 遞迴/巢狀匿名類型會導致序列化循環參考

總結

匿名類型是 C# 3.0 為 LINQ 鋪路的核心特性之一,讓「臨時資料結構」變得類型安全、語法簡潔。雖受限於方法內部,但在查詢投影、臨時 DTO、測試資料構建等場景極具表達力。現代 C# (9.0+) 的 record 類型可視為其進化版:支援名稱、可跨邊界、可繼承、可 with 更新。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性說明
不可變屬性唯讀(init-only),建構後不可修改(C# 9+ 可用 with 表達式產生副本)
強類型編譯期推斷屬性類型,IntelliSense 完整支援
值語義相等自動重寫 Equals/GetHashCode:逐屬性比較值
ToString 格式化自動生成 { Name = A, Price = 3 } 格式
範圍限制僅能作為區域變數,不可作為欄位、屬性、方法參數/返回類型(需用 object 或 dynamic 傳遞)