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

C# 3.0 匿名類型初體驗:從編譯器生成到 IL 驗證

     編輯:關於C#

匿名類型是 C# 3.0 為支援 LINQ 查詢投影而引入的核心特性。它允許在無具名類別定義的情況下,直接建立擁有強型別屬性的物件。本文從使用語法、編譯器生成機制、IL 驗證、型別身分規則全方位解析。

基本語法


var product = new { Name = "筆電", Price = 25000, InStock = true };
Console.WriteLine($"{product.Name}: {productPrice:C}"); // 強型別 IntelliSense 支援
  • 使用 var 配合 new { ... } 物件初始化器
  • 屬性名、型別由初始化運算式推斷
  • 屬性預設唯讀(僅有 get,無 set)

編譯器背後的生成機制

編譯器在編譯期自動產生一個內部類別(名稱如 <Projection>f__0),包含:

  • 對應屬性的私有欄位(<Name>k__BackingField)
  • 公共唯讀屬性(get 存取子)
  • 覆寫 Equals、GetHashCode、ToString(基於所有屬性值)
  • 建構函式接受所有屬性值

等價原始碼:


class __Anonymous1
{
    private string _name;
    private int _price;
    private bool _inStock;

    public string Name { get { return _name; } }
    public int Price { get { return _price; } }
    public bool InStock { get { return _inStock; } }

    public __Anonymous1(string name, int price, bool inStock)
    {
        _name = name; _price = price; _inStock = inStock;
    }

    public override bool Equals(object obj) { /* 比較所有屬性 */ }
    public override int GetHashCode() { /* 結合所有屬性雜湊 */ }
    public override string ToString() { /* 格式化所有屬性 */ }
}

IL 驗證

使用 ILDASM 開啟編譯後組件,可見:

  • 產生的型別名稱包含特殊字元(<>、f__),原始碼無法直接參考
  • 屬性對應 .property 定義,含 .get 方法
  • 私有欄位標記 initonly(唯讀)

型別身分與重用規則

同一組件內,若匿名類型初始化器具備:

  1. 相同屬性名稱(大小寫敏感)
  2. 相同屬性型別
  3. 相同宣告順序

編譯器會重用同一個產生型別。範例:


var a = new { Name = "A", Price = 10 };
var b = new { Name = "B", Price = 20 };      // 同型別
var c = new { Price = 10, Name = "A" };      // 不同型別(順序不同)
var d = new { Name = "A", Price = 10L };     // 不同型別(型別不同:long vs int)

a = b; // 合法
// a = c; // 編譯錯誤

跨組件限制

不同組件編譯的匿名類型永不相同,即使結構完全一致。因此:

  • 不可作為公用 API 回傳型別
  • 不可跨組件傳遞並期望型別相容
  • 序列化後反序列化將產生不同型別

適用場景總結

場景建議
LINQ select 投影✅ 最佳選擇
區域臨時資料封裝✅ 適合
單元測試資料建構✅ 方便
方法回傳值❌ 使用 Tuple/record/具名類別
公用介面參數/回傳❌ 使用具名類別
需序列化傳輸❌ 使用 DTO/record
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved