匿名型別
匿名類型提供一個便利的方法,將一組唯讀屬性封裝成一個物件,而不需要事先明確定義類型。 類型名稱會由編譯器產生,並且無法在原始程式碼層級使用。 每個屬性的類型會由編譯器推斷。
您可以使用 運算子搭配物件初始化運算式來建立匿名型 new
別。 如需物件初始設定式的詳細資訊,請參閱物件和集合初始設定式。
下列範例顯示以兩個名為 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
,以傳回來源序列中每個物件的屬性子集。 如需查詢的詳細資訊,請參閱 C# 中的 LINQ。
匿名類型包含一個或多個公用唯讀屬性。 其他類型的類別成員 (例如方法或事件) 則無效。 用於初始化屬性的運算式不可以是 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);
}
提示
您可以使用 .NET 樣式規則 IDE0037 來強制執行推斷或明確成員名稱是否為慣用。
您也可以依另一種類型的物件定義欄位:類別、結構,甚至是另一個匿名型別。 使用保存此物件的變數來完成,就像在下列範例中一樣,使用已具現化的使用者定義型別建立兩個匿名型別。 在這兩種情況下, product
匿名型 shipment
別中的欄位都會 shipmentWithBonus
是類型 Product
,其中包含每個欄位的預設值。 bonus
而且欄位會是編譯器所建立的匿名型別。
var product = new Product();
var bonus = new { note = "You won!" };
var shipment = new { address = "Nowhere St.", product };
var shipmentWithBonus = new { address = "Somewhere St.", product, bonus };
一般而言,當您使用匿名型別初始化變數時,您可以使用 var 將變數宣告為隱含型別區域變數。 由於只有編譯器可以存取匿名類型的基本名稱,因此無法在變數宣告中指定類型名稱。 如需 的詳細資訊 var
,請參閱 隱含類型區域變數。
您可以如下列範例所示,合併隱含類型區域變數和隱含類型陣列,以建立匿名類型項目的陣列。
var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};
匿名型別是 class
直接衍生自 object
的型別,而且無法轉換成除了 以外的 object
任何型別。 編譯器提供每種匿名類型的名稱,不過您的應用程式無法存取此名稱。 對 Common Language Runtime 來說,匿名類型與其他任何參考類型並無不同。
如果組件中有兩個或多個匿名物件初始設定式,指定了順序相同並具有相同名稱和類型的屬性序列,編譯器會將這些物件視為相同類型的執行個體。 這些物件會共用編譯器產生的相同類型資訊。
匿名型別以 運算式的形式支援非破壞性變化。 這可讓您建立匿名型別的新實例,其中一或多個屬性具有新的值:
var apple = new { Item = "apples", Price = 1.35 };
var onSale = apple with { Price = 0.79 };
Console.WriteLine(apple);
Console.WriteLine(onSale);
您無法將欄位、屬性、事件或方法的傳回類型,宣告為具有匿名類型。 同樣地,您無法將方法、屬性、建構函式或索引子的型式參數宣告為具有匿名類型。 若要傳遞匿名型別或包含匿名型別的集合,作為方法的引數,您可以將參數宣告為類型 object
。 不過,針對匿名型別使用 object
會破壞強型別的目的。 如果您必須在方法界限外儲存或傳遞查詢結果,請考慮使用一般具名結構或類別來取代匿名類型。
由於匿名類型上的 Equals 和 GetHashCode 方法會以屬性的 Equals
和 GetHashCode
方法來定義,相同匿名類型的兩個執行個體僅在其所有屬性都相等時,這兩個執行個體才相等。
匿名型別會覆寫 ToString 方法,串連以大括弧括住之每個屬性的名稱和 ToString
輸出。
var v = new { Title = "Hello", Age = 24 };
Console.WriteLine(v.ToString()); // "{ Title = Hello, Age = 24 }"