Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Si vous ne faites pas attention, vous pouvez, dans certaines situations, modifier drastiquement la mémoire et le profil de performance de votre application en provoquant une matérialisation prématurée des collections dans vos requêtes. Certains opérateurs de requête standard provoquent la matérialisation de leur collection source avant de générer un seul élément. Par exemple, Enumerable.OrderBy effectue une itération dans toute sa collection source, trie tous les éléments, puis génère enfin le premier élément. Cela signifie qu’il est coûteux d’obtenir le premier élément d’une collection ordonnée ; chaque élément par la suite n’est pas coûteux. Tout cela est logique : il serait impossible pour cet opérateur de requête de faire autrement.
Exemple : Ajouter une méthode qui appelle ToList, provoquant la matérialisation
Cet exemple modifie l’exemple dans Exemple de chaînage de requêtes (C#) : la méthode AppendString est modifiée pour appeler ToList avant d’effectuer une itération dans la source, ce qui provoque la matérialisation.
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();
}
}
}
Cet exemple génère la sortie suivante :
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!!!<
Dans cet exemple, vous pouvez voir que l’appel à ToList cause AppendString à énumérer l'ensemble de sa source avant de produire le premier élément. Si la source était un grand tableau, cela modifierait considérablement le profil de mémoire de l’application.
Il est également possible de chaîner les opérateurs de requête standard, comme illustré dans l'article final de ce tutoriel.