匿名型別 (C# 程式設計手冊)
更新:2011 年 4 月
匿名型別提供便利的方式將唯讀屬性集封裝至單一物件,而不必先明確定義型別。 型別名稱是由編譯器產生,而且在來源程式碼層級中無法使用。 每個屬性的型別是由編譯器推斷。
您可以使用 new 運算子搭配物件初始設定式來建立匿名型別。 如需物件初始設定式的詳細資訊,請參閱物件和集合初始設定式 (C# 程式設計手冊)。
下列範例示範透過名為 Amount 和 Message 的兩個屬性所初始化的匿名型別。
var v = new { Amount = 108, Message = "Hello" };
// Rest the mouse pointer over v.Amount and v.Message in the following
// statement to verify that their inferred types are int and string.
Console.WriteLine(v.Amount + v.Message);
匿名型別通常用於查詢運算式的 select 子句中,以從來源序列的各個物件傳回屬性子集。 如需查詢的詳細資訊,請參閱 LINQ 查詢運算式 (C# 程式設計手冊)。
匿名型別包含一個或多個公用唯讀屬性。 沒有任何其他類型的類別成員 (例如方法或事件) 是有效的。 用來初始化屬性的運算式不可以是 null、匿名函式或指標型別。
最常見的情節是使用其他型別的屬性初始化匿名型別。 下列範例假定有一個名為 Product 的類別存在。 類別 Product 包含 Color 和 Price 屬性,以及您不會感興趣的其他屬性。 變數 products 是 Product 物件的集合。 匿名型別宣告是以 new 關鍵字開頭。 宣告會初始化一個新的類型,此類型只使用兩個來自 Product 的屬性。 這會使查詢只傳回更少量的資料。
如果您未指定匿名型別中的成員名稱,編譯器會提供匿名型別成員與要對其進行初始化之屬性相同的名稱。 您必須提供名稱給要以運算式初始化的屬性,如上一個範例所示。 在下列範例中,匿名型別的屬性名稱為 Color 和 Price。
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}
當您使用匿名型別初始化變數時,通常會使用 var 將變數宣告為隱含型別區域變數。 因為只有編譯器可以存取匿名型別的基礎名稱,所以無法在變數宣告中指定型別名稱。 如需 var 的詳細資訊,請參閱隱含型別區域變數 (C# 程式設計手冊)。
您可以結合隱含型別區域變數和隱含陣列,以建立匿名型別元素的陣列,如下列範例所示。
var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};
備註
匿名型別是直接從物件衍生的類別型別。 雖然您的應用程式不能存取它,但編譯器為每個匿名型別提供了名稱。 從 Common Language Runtime 的角度來看,匿名型別只除了不能轉換成物件以外的任何型別,與其他任何參考型別並無不同。
如果同一個組件中的兩個或兩個以上的匿名型別具有相同數目及型別的屬性且其屬性順序相同,則編譯器會將這些匿名型別視為相同型別。 它們會共用編譯器產生的相同型別資訊。
您無法將欄位、屬性、事件或方法傳回型別宣告為具有匿名型別。 同樣地,您不能宣告有匿名型別之方法、屬性、建構函式或索引子的正式參數。 若要傳遞匿名型別或包含匿名型別的集合做為方法的引數,您可以將參數宣告為 object 型別。 但是,這樣做失去強型別的目的。 如果您必須在方法界限外儲存或傳遞查詢結果,請考慮使用一般的具名結構或類別,而不使用匿名型別。
因為匿名型別上的 Equals 和 GetHashCode 方法是根據屬性的 Equals 和 GetHashcode 方法定義,相同匿名型別的兩個執行個體只有在其所有屬性都相等時才會相等。
請參閱
參考
概念
其他資源
變更記錄
日期 |
記錄 |
原因 |
---|---|---|
2011 年 4 月 |
釐清文字。 |
客戶回函。 |