Zwischenmaterialisierung (C#)Intermediate Materialization (C#)

Bei fehlender Sorgfalt kann es in bestimmten Situationen dazu kommen, dass die Auflistungen in Ihren Abfragen vorzeitig materialisiert werden, wodurch sich das Speicher- und Leistungsprofil Ihrer Anwendung radikal ändert.If you are not careful, in some situations you can drastically alter the memory and performance profile of your application by causing premature materialization of collections in your queries. Einige Standardabfrageoperatoren verursachen die Materialisierung ihrer Quellauflistung, bevor auch nur ein einziges Element zurückgegeben wird.Some standard query operators cause materialization of their source collection before yielding a single element. So durchläuft beispielsweise Enumerable.OrderBy zuerst die gesamte Quellauflistung, sortiert dann alle Elemente und gibt zum Schluss das erste Element zurück.For example, Enumerable.OrderBy first iterates through its entire source collection, then sorts all items, and then finally yields the first item. Das bedeutet, dass es zwar aufwendig ist, das erste Element einer sortierten Auflistung abzurufen, das Abrufen aller folgenden Elemente hingegen ist nicht aufwendig.This means that it is expensive to get the first item of an ordered collection; each item thereafter is not expensive. Dies ist sinnvoll, denn anders würde dieser Abfrageoperator nicht funktionieren.This makes sense: It would be impossible for that query operator to do otherwise.

BeispielExample

Dieses Beispiel ändert das vorherige Beispiel.This example alters the previous example. Die AppendString-Methode ruft vor dem Durchlaufen der Quelle ToList auf.The AppendString method calls ToList before iterating through the source. Dies verursacht eine Materialisierung.This causes materialization.

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();  
        }  
    }  
}  

Dieses Beispiel erzeugt die folgende Ausgabe:This example produces the following output:

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!!!<  

Diesem Beispiel können Sie entnehmen, dass der Aufruf von ToList AppendString dazu veranlasst, vor der Rückgabe des ersten Elements seine gesamte Quelle aufzulisten.In this example, you can see that the call to ToList causes AppendString to enumerate its entire source before yielding the first item. Wenn die Quelle ein großes Array wäre, würde dies das Arbeitsspeicherprofil der Anwendung deutlich verändern.If the source were a large array, this would significantly alter the memory profile of the application.

Standardabfrageoperatoren können auch miteinander verkettet werden.Standard query operators can also be chained together. Informationen dazu finden Sie im letzten Thema dieses Lernprogramms:The final topic in this tutorial illustrates this.

Siehe auchSee Also

Tutorial: Verketten von Abfragen (C#)Tutorial: Chaining Queries Together (C#)