270 Stimmen

LINQ: Ein Objekt auswählen und einige Eigenschaften ändern, ohne ein neues Objekt zu erstellen

Ich möchte einige Eigenschaften eines LINQ-Abfrageergebnisobjekts ändern, ohne ein neues Objekt zu erstellen und jede Eigenschaft manuell einzustellen. Ist dies möglich?

Beispiel:

var list = from something in someList
           select x // but change one property

1 Stimmen

Das tut mir leid! Hier ist die richtige Adresse: robvolk.com/

1 Stimmen

2 Stimmen

Dies ist zwar möglich, wie die Antworten zeigen, aber beachten Sie bitte, dass dies gegen die Natur von LINQ verstößt. LINQ-Methoden sollen keine Seiteneffekte verursachen, so dass diese Vorgehensweise nicht dem Prinzip der geringsten Überraschung entspricht. Gemäß LINQ würden Sie die Objekte abrufen und sie dann ändern.

12voto

Daniel Brückner Punkte 57561

Mit den Standard-Abfrageoperatoren ist dies nicht möglich - es handelt sich um eine sprachintegrierte Abfrage, nicht um eine sprachintegrierte Aktualisierung. Aber Sie könnten Ihre Aktualisierung in Erweiterungsmethoden verstecken.

public static class UpdateExtension
{
    public static IEnumerable<Car> ChangeColorTo(
       this IEnumerable<Car> cars, Color color)
    {
       foreach (Car car in cars)
       {
          car.Color = color;
          yield return car;
       }
    }
}

Jetzt können Sie es wie folgt verwenden.

cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);

1 Stimmen

Es geht nicht darum, dass Sie die Basissammlung aktualisieren wollen. Wir wollen die Eigenschaft der Ergebnissammlung aktualisieren.

4 Stimmen

Nun, LINQ ersetzt SQL, was für Structured Abfrage Sprache, aber es zeigt immer noch die Fähigkeit, die UPDATE , DELETE y INSERT . Ich würde also nicht behaupten, dass es die Semantik ist, die diese Funktion verhindert.

2voto

Informitics Punkte 77

Dies ist häufig der Fall, wenn wir einen Indexwert sowie den ersten und letzten Indikator in eine Liste aufnehmen wollen, ohne ein neues Objekt zu erstellen. Auf diese Weise können Sie die Position des Elements in Ihrer Liste, Aufzählung usw. kennen, ohne die vorhandene Klasse ändern zu müssen und ohne zu wissen, ob Sie sich am ersten oder am letzten Element der Liste befinden.

foreach (Item item in this.Items
    .Select((x, i) => {
    x.ListIndex = i;
    x.IsFirst = i == 0;
    x.IsLast = i == this.Items.Count-1;
    return x;
}))

Sie können einfach jede Klasse erweitern, indem Sie:

public abstract class IteratorExtender {
    public int ListIndex { get; set; }
    public bool IsFirst { get; set; } 
    public bool IsLast { get; set; } 
}

public class Item : IteratorExtender {}

1voto

Stefan R. Punkte 387

Da ich hier nicht die Antwort gefunden habe, die ich für die beste Lösung halte, hier mein Weg:

Die Verwendung von "Select" zur Änderung von Daten ist möglich, aber nur mit einem Trick. Jedenfalls ist "Select" nicht dafür gedacht. Es führt die Änderung nur aus, wenn es mit "ToList" verwendet wird, da Linq nicht ausgeführt wird, bevor die Daten benötigt werden. Wie auch immer, die beste Lösung ist die Verwendung von "foreach". Im folgenden Code können Sie das sehen:

    class Person
    {
        public int Age;
    }

    class Program
    {
        private static void Main(string[] args)
        {
            var persons = new List<Person>(new[] {new Person {Age = 20}, new Person {Age = 22}});
            PrintPersons(persons);

            //this doesn't work:
            persons.Select(p =>
            {
                p.Age++;
                return p;
            });
            PrintPersons(persons);

            //with "ToList" it works
            persons.Select(p =>
            {
                p.Age++;
                return p;
            }).ToList();
            PrintPersons(persons);

            //This is the best solution
            persons.ForEach(p =>
            {
                p.Age++;
            });
            PrintPersons(persons);
            Console.ReadLine();
        }

        private static void PrintPersons(List<Person> persons)
        {
            Console.WriteLine("================");
            foreach (var person in persons)
            {
                Console.WriteLine("Age: {0}", person.Age);
            ;
            }
        }
    }

Vor "foreach" können Sie auch eine linq-Auswahl treffen...

1voto

Victor Wilson Punkte 1226

Im Jahr 2020 verwende ich die MoreLinq Pipe Methode. https://morelinq.github.io/2.3/ref/api/html/M_MoreLinq_MoreEnumerable_Pipe__1.htm

0voto

Solmead Punkte 3999
var item = (from something in someList
       select x).firstordefault();

würde die item und dann könnten Sie Folgendes tun item.prop1=5; um die jeweilige Eigenschaft zu ändern.

Oder möchten Sie eine Liste von Elementen aus der Datenbank abrufen und die Eigenschaft prop1 für jedes Element in der zurückgegebenen Liste auf einen bestimmten Wert setzen? Wenn ja, könnten Sie dies tun (ich tue es in VB, weil ich es besser kenne):

dim list = from something in someList select x
for each item in list
    item.prop1=5
next

( list enthält alle Elemente, die mit Ihren Änderungen zurückgegeben werden)

0 Stimmen

Während dies funktioniert, denke ich, dass die OP gefragt wurde, wie die LINQ-Anweisung zu schreiben, ohne ein zu schreiben for each Schleife.

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