LINQ: Wählen Sie ein Objekt aus und ändern Sie einige Eigenschaften, ohne ein neues Objekt zu erstellen

Wenn ich mit LINQ eine Abfrage ausführen und das Objekt aus der Abfrage zurückgeben, aber nur einige der Eigenschaften in diesem Objekt ändern möchte, wie würde ich dies tun, ohne ein neues Objekt zu erstellen und jede Eigenschaft manuell festzulegen? Ist das möglich?

Beispiel:

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

Ich bin mir nicht sicher, was die Abfragesyntax ist. Aber hier ist das erweiterte Beispiel für den LINQ-Ausdruck.

 var query = someList.Select(x => { x.SomeProp = "foo"; return x; }) 

Was dies tut, ist eine anonyme Methode vs und Ausdruck verwenden. Dadurch können Sie mehrere statementen in einem Lambda verwenden. Sie können also die beiden Operationen des Festlegens der Eigenschaft und des Zurückgebens des Objekts in diese etwas prägnante Methode kombinieren.

Wenn Sie nur die Eigenschaft für alle Elemente aktualisieren möchten, dann

 someList.All(x => { x.SomeProp = "foo"; return true; }) 

Ich bevorzuge dieses hier. Es kann mit anderen linq-Befehlen kombiniert werden.

 from item in list let xyz = item.PropertyToChange = calcValue() select item 

Es sollte keine LINQ-Magie geben, die dich daran hindert, dies zu tun. Verwenden Sie keine Projektion, die einen anonymen Typ zurückgibt.

 User u = UserCollection.FirstOrDefault(u => u.Id == 1); u.FirstName = "Bob" 

Das wird das reale Objekt verändern, sowie:

 foreach (User u in UserCollection.Where(u => u.Id > 10) { u.Property = SomeValue; } 

Dies ist mit den Standardabfrageoperatoren nicht möglich – es handelt sich um eine sprachintegrierte Abfrage, nicht um ein sprachintegriertes Update. Aber Sie könnten Ihr Update in Erweiterungsmethoden verstecken.

 public static class UpdateExtension { public static IEnumerable ChangeColorTo( this IEnumerable 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); 
 var item = (from something in someList select x).firstordefault(); 

Würde den Gegenstand bekommen, und dann könntest du item.prop1 = 5 machen; um die spezifische Eigenschaft zu ändern.

Oder möchten Sie eine Liste von Elementen aus der database abrufen und die Eigenschaft prop1 für jedes Element in der zurückgegebenen Liste auf einen bestimmten Wert ändern? Wenn ja, könntest du das machen (ich mache es in VB, weil ich es besser weiß):

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

(Die Liste enthält alle Elemente, die mit Ihren Änderungen zurückgegeben wurden.)

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

Mit “Select” können Daten geändert werden, aber nur mit einem Trick. Wie auch immer, “Select” ist dafür nicht gemacht. 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 “foreach”. Im folgenden Code können Sie sehen:

  class Person { public int Age; } class Program { private static void Main(string[] args) { var persons = new List(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 persons) { Console.WriteLine("================"); foreach (var person in persons) { Console.WriteLine("Age: {0}", person.Age); ; } } } 

Vor “foreach” können Sie auch eine linq Auswahl treffen …

Wenn Sie Elemente mit einer Where Klausel aktualisieren möchten, wird die Verwendung von .Where (…) Ihre Ergebnisse abschneiden, wenn Sie Folgendes tun:

 mylist = mylist.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList(); 

Sie können Updates für bestimmte Elemente in der Liste wie folgt ausführen:

 mylist = mylist.Select(n => { if (n.Id == ID) { n.Property = ""; } return n; }).ToList(); 

Geben Sie den Artikel immer zurück, auch wenn Sie keine Änderungen vornehmen. Auf diese Weise wird es in der Liste gespeichert.

Wir stoßen oft auf diesen Punkt, wo wir den Indexwert und die ersten und letzten Indikatoren in eine Liste aufnehmen wollen, ohne ein neues Objekt zu erstellen. Dadurch können Sie die Position des Elements in Ihrer Liste, Enumeration usw. kennen, ohne die vorhandene class ändern zu müssen und dann zu wissen, ob Sie an der ersten oder letzten Position stehen.

 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 class erweitern mit:

 public abstract class IteratorExtender { public int ListIndex { get; set; } public bool IsFirst { get; set; } public bool IsLast { get; set; } } public class Item : IteratorExtender {} 
 User u = UserCollection.Single(u => u.Id == 1); u.FirstName = "Bob"