10 Stimmen

Warum wird diese LINQ-Abfrage nicht ausgeführt, wenn foreach verwendet wird?

Beim Erstellen neuer Objekte in einer LINQ-Anweisung, zum Beispiel:

var list = new List() { "a", "b", "c" };
var erstellt = from i in list select new A();

Mit der Klasse A, die so aussieht:

Klasse A
{
    public string Label;
}

Und dann die Eigenschaften in A mit einer foreach-Schleife ändern:

foreach (var c in erstellt) {
    c.Label = "Set";
}

Warum werden die Werte nicht gesetzt, wenn man anschließend auf die Objekte im IEnumerable zugreift. z.B. die folgende Assertion schlägt fehl:

Assert.AreEqual("Set", erstellt.ElementAt(2).Label);

Ich frage mich, warum das passiert. Ich würde erwarten, dass die foreach-Anweisung die Abfrage ausführt und die Erstellung der Objekte auslöst. Die MSDN-Dokumentation besagt: "Die Ausführung der Abfrage wird verzögert, bis die Abfragevariable in einer foreach- oder For Each-Schleife durchlaufen wird".

Ich habe dieses Verhalten mit .NET 4.5 und Mono 3.2.0 reproduziert. Das Problem verschwindet, wenn man ToList auf dem IEnumerable aufruft, bevor man auf das erstellte Objekt zugreift.

6voto

RobSiklos Punkte 7759

Es passiert, weil erstellt eine Abfrage ist, kein Ergebnis. Jedes Mal, wenn Sie es aufzählen, wird das Wählen erneut von Grund auf ausgewertet.

Wenn Sie möchten, dass dies funktioniert, machen Sie erstellt zu einer tatsächlichen Liste, anstatt nur ein IEnumerable, das eine Abfrage darstellt.

Zum Beispiel hinzufügen:

erstellt = erstellt.ToList();

Sie sagen:

Ich würde erwarten, dass die foreach-Anweisung die Abfrage ausführt und die Erstellung der Objekte auslöst

Genau das passiert. Das Problem ist, dass die Erstellung der Objekte jedes Mal passiert, wenn Sie über erstellt iterieren, nicht nur beim ersten Mal. Da die Methode ElementAt() über erstellt iteriert, erstellt sie einfach erneut neue A Objekte.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X