匿名型別

匿名類型提供一個便利的方法,將一組唯讀屬性封裝成一個物件,而不需要事先明確定義類型。 類型名稱會由編譯器產生,並且無法在原始程式碼層級使用。 每個屬性的類型會由編譯器推斷。

您可以使用 運算子搭配物件初始化運算式來建立匿名型 new 別。 如需物件初始設定式的詳細資訊,請參閱物件和集合初始設定式

下列範例顯示以兩個名為 AmountMessage 的屬性初始化的匿名類型。

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 類別包含 ColorPrice 屬性,以及您不感興趣的其他屬性。 變數 productsProduct 物件的集合。 匿名類型宣告的開頭為 new 關鍵字。 宣告會初始化新類型,只使用 Product 中的兩個屬性。 使用匿名型別會導致查詢中傳回較少的資料量。

如果您未在匿名型別中指定成員名稱,編譯器會提供匿名型別成員與用來初始化它們的屬性相同的名稱。 您可以提供正以運算式初始化的屬性名稱,如上一個範例所示。 在下列範例中,匿名類型的屬性名稱是 ColorPrice

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 會破壞強型別的目的。 如果您必須在方法界限外儲存或傳遞查詢結果,請考慮使用一般具名結構或類別來取代匿名類型。

由於匿名類型上的 EqualsGetHashCode 方法會以屬性的 EqualsGetHashCode 方法來定義,相同匿名類型的兩個執行個體僅在其所有屬性都相等時,這兩個執行個體才相等。

匿名型別會覆寫 ToString 方法,串連以大括弧括住之每個屬性的名稱和 ToString 輸出。

var v = new { Title = "Hello", Age = 24 };

Console.WriteLine(v.ToString()); // "{ Title = Hello, Age = 24 }"