3.3 延遲的查詢賦值(Deferred Query Evaluation)
機(jī)敏的讀者(Observant readers)可能注意到標(biāo)準(zhǔn)的 Where 操作符在 C# 2.0 介紹里是用 yield 構(gòu)造(construct)實(shí)現(xiàn)的。這是所有的標(biāo)準(zhǔn)操作符返回(return)有序列的數(shù)據(jù)(sequences of values)所采用的共同的實(shí)現(xiàn)技術(shù)。yield 關(guān)鍵詞的用途有個(gè)很有趣的好處,就是查詢實(shí)際是直到迭代結(jié)束(iterated over)后才被賦值的,即使是 foreach 語句或者手工使用下面(underlying)的 GetEnumerator 和 MoveNext 方法也是如此。這種延遲的賦值方式允許查詢像基于 IEnumerable<T> 值(IEnumerable<T>-based values)一樣保留著,在每次 yield 方式返回可能不同的結(jié)果(yielding potentially different results)的時(shí)候可以被賦值多次(evaluated multiple times)。
對許多應(yīng)用程序來說,這是期望(desired)得到的準(zhǔn)確的行為(is exactly the behavior)。對應(yīng)用程序想緩存查詢賦值的結(jié)果,ToList 和 ToArray 這兩個(gè)操作符提供用來強(qiáng)制查詢的直接賦值(force the immediate evaluation),以返回一個(gè)含有查詢賦值的結(jié)果的 List<T> 或者Array 數(shù)組。
為了解延遲查詢賦值是怎么工作的,請考察下面一段簡單地查詢一個(gè)數(shù)組的程序:
// declare a variable containing some strings

string[] names =
{ "Allen", "Arthur", "Bennett" };

// declare a variable that represents a query
IEnumerable<string> ayes = names.Where(s => s[0] == 'A');

// evaluate the query
foreach (string item in ayes)
Console.WriteLine(item);

// modify the original information source
names[0] = "Bob";

// evaluate the query again, this time no "Allen"
foreach (string item in ayes)
Console.WriteLine(item);

查詢在每次變量 ayes 迭代結(jié)束(iterated over)時(shí)賦值。為了顯示需要對結(jié)果做一份緩存的copy,我們可以簡單給這個(gè)查詢附加上一個(gè) ToList 或 一個(gè) ToArray 操作符,如下所示:
// declare a variable containing some strings

string[] names =
{ "Allen", "Arthur", "Bennett" };

// declare a variable that represents the result
// of an immediate query evaluation
string[] ayes = names.Where(s => s[0] == 'A').ToArray();

// iterate over the cached query results
foreach (string item in ayes)
Console.WriteLine(item);

// modifying the original source has no effect on ayes
names[0] = "Bob";

// iterate over result again, which still contains "Allen"
foreach (string item in ayes)
Console.WriteLine(item);

ToList 和 ToArray 都強(qiáng)制查詢的賦值,就像執(zhí)行一個(gè)標(biāo)準(zhǔn)查詢操作符(如 First, ElementAt, Sum, Average, All, 等)返回一個(gè)單獨(dú)的值(singleton values)一樣。
待續(xù), 錯(cuò)誤難免,請批評指正,譯者Naven 2005-10-22