Delen via


Tussenliggende materialisatie (C#)

Als u niet voorzichtig bent, kunt u in sommige situaties het geheugen- en prestatieprofiel van uw toepassing drastisch wijzigen door voortijdige materialisatie van verzamelingen in uw query's te veroorzaken. Sommige standaardqueryoperators veroorzaken materialisatie van hun bronverzameling voordat ze één element opleveren. Als u bijvoorbeeld Enumerable.OrderBy eerst de hele bronverzameling doorloopt, sorteert u vervolgens alle items, waarna het eerste item uiteindelijk wordt weergegeven. Dit betekent dat het duur is om het eerste item van een bestelde verzameling op te halen; elk item daarna is niet duur. Dit is logisch; Het zou onmogelijk zijn dat die queryoperator anders kan worden uitgevoerd.

Voorbeeld: Een methode toevoegen die aanroept ToList, waardoor materialisatie wordt veroorzaakt

In dit voorbeeld wordt het voorbeeld van chainquery's (C#) gewijzigd: de AppendString methode wordt gewijzigd om aan te roepen ToList voordat de bron wordt herhaald, wat materialisatie veroorzaakt.

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

In dit voorbeeld wordt de volgende uitvoer gegenereerd:

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

In dit voorbeeld ziet u dat de aanroep om de ToListAppendString volledige bron op te sommen voordat het eerste item wordt weergegeven. Als de bron een grote matrix was, zou dit het geheugenprofiel van de toepassing aanzienlijk veranderen.

Standaardqueryoperators kunnen ook worden gekoppeld, zoals wordt weergegeven in het laatste artikel in deze zelfstudie:

Zie ook