3.5 結構型值和類型(Structured values and types)
LINQ 項目以數據為中心的程序設計格式(data-centric programming style),有些類型存在的主要目的是在結構型值之上(over a structured value)提供一個靜態的“shape”(static "shape"),這勝過同時有聲明(state)和行為(behavior)的完全成熟(full-blown)的對象。對它的邏輯結論(logical conclusion)作出這個假設(taking this premise),最常見的情形(is often the case)是所有的開發者當心(cares about)值的結構(structure of the value),對這個 shape 一個命名的類型(named type)的需要(the need for)是幾乎無用的(is of little use)。這導致(leads to)匿名類型(anonymous types)的介紹(introduction)允許新的結構(structures)給它們的初始化(initialization)定義成“inline”。
在 C# 語言里,匿名類型(anonymous types)與對象初始化的語法(object initialization syntax)是一樣的(is identical to),除了類型的名字(name of the type)被忽略(omitted)了。例于,考察下面的兩段語句:

object v1 = new Person
{
Name = "Chris Smith", Age = 31, CanCode = false
};


object v2 = new
{ // note the omission of type name
Name = "Chris Smith", Age = 31, CanCode = false
};

變量 v1 和 v2 都指向一個內存中的對象(in-memory object),它的 CLR 類型有三個公共的屬性(public properties):Name,Age,和CanCode。它們的不同之處(differ in)是 v2 引用自(refers to)一個匿名類型(anonymous types)的實體。在 CLR 中(in CLR terms),匿名類型與任何其他類型沒有什么不同。使得匿名類型特殊(special)的是它們在你的程序開發語言中沒有特殊意義的名字(have no meaningful name)。創建一個匿名類型的實體(instances of an anonymous type)的唯一途經就是使用上面所示的語法。
為了允許變量引用匿名類型的實體仍然需要利用(benefit from)靜態類型(static typing),C# 介紹 var 關鍵詞時說它可以用于局部變量定義(local variable declarations)的類型名稱(type name),例于,考察下面這段合法(legal)的 C# 3.0 程序:
var s = "Bob";
var n = 32;
var b = true;

關鍵詞 var 告訴編譯器從用來初始化變量的表達式的靜態類型(static type)來推斷(infer)這個變量的類型。在這個例子中,變量 s,n 和 b 的類型分別(respectively)是 string,int 和 bool,這段程序和下面的程序是一樣的:
string s = "Bob";
int n = 32;
bool b = true;

關鍵詞 var 對那些類型有特殊含義名稱(meaningful names)的變量是一個方便的工具(convenience),但是它對引用自匿名類型的實體的變量(instances of anonymous types)卻是必需的(necessity)。

var value = new
{
Name = "Chris Smith", Age = 31, CanCode = false
};

在上面的例子中,變量 value 是一個匿名類型,它的定義與下面的 C# 偽代碼(pseudo-C#:)是相等的(equivalent to):

internal class ???
{
string _Name;
int _Age;
bool _CanCode;


public string Name
{

get
{ return _Name; } set
{ _Name = value; }
}


public int Age
{

get
{ return _Age; } set
{ _Age = value; }
}


public bool CanCode
{

get
{ return _CanCode; } set
{ _CanCode = value; }
}
}

匿名類型不能被共享于(shared)跨越(across)匯編后代碼的邊界(assembly boundaries),但是編譯保證(ensures)在每段匯編代碼中(within each assembly)對被賦予的(given)成 name/type 對(name/type pairs)的屬性序列(sequence of property)最多只有一個匿名類型。
因為匿名類型常常被用在從一個現有的結構型值(an existing structured value)中選取它的一個或更多的成員的投影(projections)中,這樣我們就能夠簡單地在一個匿名類型的初始化(initialization of an anonymous type)中從另一個值引用(reference)域(fields)或屬性(properties)。這導致(results in)匿名類型獲取到一個屬性(property),它的名稱(name),類型(type)和值(value)都拷貝自引用的屬性或域(referenced property or field)。
舉例來說,下面的程序通過從其他值中結合屬性(combining properties)來創建一個新的結構性值(structured value):

var bob = new Person
{ Name = "Bob", Age = 51, CanCode = true };

var jane = new
{ Age = 29, FirstName = "Jane" };


var couple = new
{

Husband = new
{ bob.Name, bob.Age },

Wife = new
{ Name = jane.FirstName, jane.Age }
};

int ha = couple.Husband.Age; // ha == 51
string wn = couple.Wife.Name; // wn == "Jane"

上面展示的引用域(fields)或屬性(properties)的代碼是與下面寫出的更明顯的形式(more explicit form)的一種更簡單方便的語法(is simply a convenient syntax):

var couple = new
{

Husband = new
{ Name = bob.Name, Age = bob.Age },

Wife = new
{ Name = jane.FirstName, Age = jane.Age }

};

在兩種形式中(in both cases),變量 couple 都從變量 bob 和 jane 中的 Name 和 Age 屬性獲取了一份自己的 copy 。
匿名類型通常用于查詢的 select 語句(select clause),例于,看下面的查詢程序:

var expr = people.Select(p => new
{
p.Name, BadCoder = p.Age == 11
});

foreach (var item in expr)
Console.WriteLine("{0} is a {1} coder",
item.Name,
item.BadCoder ? "bad" : "good");

在這個例子中我們能夠在類型 Person 上創建一個新的投影(projection),它正確地符合(exactly matched)我們的執行代碼(processing code)所需要的形態(shape),但是仍然具有靜態類型(static type)的好處(the benefits of)。
待續, 錯誤難免,請批評指正,譯者Naven 2005-10-23