Come aggiornare il valore in un elenco utilizzando LINQ

Ho una lista che voglio aggiornare usando LINQ.

class Student { private string name; private int marks; public string Name { get; set;} public int Marks { get; set; } public Student(string name, int marks) { Name = name; Marks = marks; } } List myList = new List(); myList.Add(new Student("John", 10)); myList.Add(new Student("Tom", 20)); 

Ora voglio aggiornare l’elenco usando LINQ in modo tale che solo i segni di John vengano aggiornati. Sto usando la seguente syntax:

 myList.Where(w => w.Name == "Tom").Select(w=> { w.Marks = 35; return w}); 

Ma questo non aggiorna i dati in myList. Qualcuno può dirmi dove sbaglio?

LINQ è per l’interrogazione, non per l’aggiornamento dei dati. Utilizzare LINQ per ottenere gli elementi che si desidera modificare e quindi modificarli in un ciclo foreach :

 foreach ( var tom in myList.Where(w => w.Name == "Tom")) { tom.Marks = 35; } 

Demo.

Come altri hanno sottolineato, LINQ è per interrogare i dati, non è per fare aggiornamenti.

Dovresti iterare la tua lista e modificare i tuoi valori come:

 foreach (var student in myList) { if (student.Name == "Tom") { student.Marks = 35; } } 

O

 foreach (var student in myList.Where(r => r.Name == "Tom")) { student.Marks = 35; } 

Qualunque cosa tu pensi meglio, trasmette l’intento.


ma qui è una cosa interessante:

Se hai una dichiarazione del tipo:

 myList.Where(w => w.Name == "Tom").Select(w => w.Marks = 35).ToList(); 

Senza assegnare il risultato a myList la query sopra riportata modificherà il valore nell’elenco originale. Ricorda, è un effetto collaterale e non è il modo corretto per aggiornare . Questa modifica può essere spiegata dal parametro di riferimento che viene passato a un metodo e modificato lì. Ma, soprattutto, questo dovrebbe sempre essere evitato . È una ctriggers pratica e potrebbe portare a codice davvero confuso. Utilizzare LINQ solo per le query.

Provare:

 myList .Where(w=> w.Name == "dTomi").ToList().ForEach(i => i.Marks = 35); 

che ne dici di buon vecchio for ciclo

 for(int i = 0; i < myList.Count; i++) if (myList[i].Name == "Tom") { myList[i].Marks = 35; break; } 

beh, il codice @dasblinkenlight dovrebbe funzionare ma puoi anche provare qualcosa di simile

  var query = from x in list where x.Name = yourcondition select new { x }; foreach(var item in query) item.x.FieldToUpdate = SetValue; 

Questo è un po ‘goffo, ma funziona, e non dipende dall’essere passato un riferimento. Crea una nuova lista basata sul vecchio.

 var myList=myList.Select(l=>new Student { l.Name, Marks=l.Name=="Tom"?35:l.Marks}).ToList(); 

O più sciocco:

 var myList=myList.Where(l=>l.Name!="Tom").Union( myList.Where(l=>l.Name=="Tom").Select(l=>new Student { l.Name, Marks=35})).ToList(); 

Gli oggetti sono memorizzati per riferimento nell’elenco in modo da poter recuperare oggetti tramite linq e quindi modificare, rifletteranno le modifiche sull’elenco.

Esempio

  static void Main(string[] args) { List testList = new List() { new Entity() {Id = 1, Text = "Text"}, new Entity() {Id = 2, Text = "Text2"} }; Console.WriteLine($"First text value:{testList[1].Text}"); Entity entityToEdit = testList.FirstOrDefault(e => e.Id == 2); if (entityToEdit != null) entityToEdit.Text = "Hello You!!"; Console.WriteLine($"Edited text value:{testList[1].Text}"); Console.ReadLine(); } internal class Entity { public int Id { get; set; } public String Text { get; set; } } 

Provando l’app otterrai il seguente risultato:

Primo valore di testo: Testo2

Valore del testo modificato: Ciao !!

Sopra può essere raggiunto semplicemente assegnando il valore alla raccolta

 myList = myList .Where(w => w.Name == "Tom") .Select(w=> { w.Marks = 35; return w}) .ToList();