Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Если вы не будете осторожны и внимательны, то в некоторых ситуациях можете существенно изменить характеристики памяти и производительности вашего приложения, вызвав преждевременную материализацию коллекций в запросах. Некоторые стандартные операторы запросов вызывают материализацию исходной коллекции перед получением одного элемента. Например, 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 перебирает весь свой источник перед тем, как получить первый элемент. Если источник был большим массивом, это значительно изменит профиль памяти приложения.
Операторы стандартных запросов также можно объединить в цепочку, как показано в заключительной статье в этом руководстве: