原文:《C# Version 3.0 Specification》,Microsoft
翻譯:lover_P
C# 3.0允許將new運算符用於一個匿名對象初始化器來創建一個匿名類型的對象。
primary-no-array-creation-expression:
...
anonymous-object-creation-expression
anonymous-object-creation-expression:
new anonymous-object-initializer
anonymous-object-initializer:
{ member-declarator-listopt }
{ member-declarator-list , }
member-declarator-list:
member-declarator
member-declarator-list , member-declarator
member-declarator:
simple-name
member-Access
identifIEr = expression
一個匿名對象初始化器聲明了一個匿名類型並返回了該類型的一個實例。匿名類型是一個沒有名字並且直接繼承自object的類類型。匿名類型的成員是一系列可讀/寫屬性,這些屬性依次通過創建該類型的實例時使用的對象初始化器進行推斷。特殊地,具有下面形式的一個匿名對象初始化器:
new { p1 = e1 , p2 = e2, ... pn = en }
聲明了一個具有下面形式的匿名類型:
class __Anonymous1
{
private T1 f1;
private T2 f2;
...
private Tn fn;
public T1 p1 { get { return f1; } set { f1 = value; } }
public T2 p2 { get { return f2; } set { f2 = value; } }
...
public Tn pn { get { return fn; } set { fn = value; } }
}
其中的每個Tx是對應的表達式ex的類型。如果匿名對象初始化器中的某個表達式具有空類型,會發生一個編譯期錯誤。
匿名類型的名字由編譯器自動生成,並且不能在程序文本中引用。
在同一個程序中,兩個具有相同名字、相同類型和相同順序的屬性的匿名對象初始化器將產生同一個匿名類型的實例。(這個定義包括了屬性的順序,這是因為在某些環境中順序是可見的而且是非常重要的,比如反射。)
下面的例子:
var p1 = new { Name = "Lawnmower", Price = 495.00 };
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;
其中最後一行中的賦值是允許的,因為p1和p2具有相同的匿名類型。
一個成員初始化器可以縮寫為一個簡單名字或一個成員訪問。這時稱該成員初始化器為發散性初始化器(Projection Initializer),也是對具有相同名字的屬性的聲明和賦值的簡寫。特別地,具有下面形式的成員聲明器:
identifIEr
expr . identifIEr
與下面的對應形式完全等價:
identifier = identifIEr
identifier = expr . identifIEr
因此,在一個發散性的初始化器中,identifIEr同時選擇了所賦的值的值和域或屬性。直觀上看,發散性的初始化器反映出的不僅僅是一個值,還包括這個值的名字。