中繼具體化 (C#)
如果不小心,在某些情況下,您可能會造成查詢中的集合過早具體化,從而徹底改變應用程式的記憶體與效能設定檔。 有些標準查詢運算子會在產生單一項目前,造成其來源集合具體化。 例如,Enumerable.OrderBy 會先逐一查看其完整的來源集合,然後排序所有的項目,最後產生第一個項目。 也就是說,取得順序集合的第一個項目會高度耗費資源;之後每個項目則不會高度耗費資源。 這很合理;否則,該查詢運算子不可能這麼做。
範例:新增呼叫 ToList
的方法,導致具體化
本範例會改變鏈結查詢範例 (C#) 中的範例:AppendString
方法會變更為在逐一查看來源之前呼叫 ToList,這會導致具體化。
public static class LocalExtensions
{
public static IEnumerable<string>
ConvertCollectionToUpperCase(this IEnumerable<string> source)
{
foreach (string str in source)
{
Console.WriteLine("ToUpper: source >{0}<", str);
yield return str.ToUpper();
}
}
public static IEnumerable<string>
AppendString(this IEnumerable<string> source, string stringToAppend)
{
// the following statement materializes the source collection in a List<T>
// before iterating through it
foreach (string str in source.ToList())
{
Console.WriteLine("AppendString: source >{0}<", str);
yield return str + stringToAppend;
}
}
}
class Program
{
static void Main(string[] args)
{
string[] stringArray = { "abc", "def", "ghi" };
IEnumerable<string> q1 =
from s in stringArray.ConvertCollectionToUpperCase()
select s;
IEnumerable<string> q2 =
from s in q1.AppendString("!!!")
select s;
foreach (string str in q2)
{
Console.WriteLine("Main: str >{0}<", str);
Console.WriteLine();
}
}
}
這個範例會產生下列輸出:
ToUpper: source >abc<
ToUpper: source >def<
ToUpper: source >ghi<
AppendString: source >ABC<
Main: str >ABC!!!<
AppendString: source >DEF<
Main: str >DEF!!!<
AppendString: source >GHI<
Main: str >GHI!!!<
在此範例中,您可以了解呼叫 ToList 會造成 AppendString
列舉其完整來源,然後再產生第一個項目。 如果來源是大型陣列,這會明顯改變應用程式的記憶體設定檔。
標準查詢運算子也可以鏈結在一起,如本教學課程的最後一篇文章所示: