Modo semplice per aggiornare oggetti IEnumerable usando LINQ

Supponiamo che io abbia un object business come questo,

class Employee { public string name; public int id; public string desgination; public int grade; } List lstEmp = new List() { new Employee() { name="A",desgination="SE",id=1}, new Employee() { name="b",desgination="TL",id=2}, new Employee() { name="c",desgination="PL",id=3}, new Employee() { name="d",desgination="SE",id=4}, new Employee() { name="e",desgination="SSE",id=5}, }; 

E se voglio aggiornare il grado del dipendente a 3 la cui designazione è “SE”, allora devo scrivere qualcosa del genere

 lstEmp=lstEmp.Select(x => { x.grade = (x.desgination == "SE") ? 3 : x.grade; return x; }).ToList(); 

Ma qui quando si utilizza select genererà ogni volta un nuovo object dipendente, non aggiornando l’esistente lstEmp, quindi devo riassegnare l’elenco aggiornato a lstEmp.

Mi sembra che influenzi le prestazioni durante l’aggiornamento frequente di aggiornamenti di grandi dimensioni. C’è una soluzione per questo?

Credo che i metodi LINQ predefiniti non supportino gli aggiornamenti in linea. ma è ansible creare i propri metodi di estensione per ottenere questo

  public static void Update(this IEnumerable outer, Action updator) { foreach (var item in outer) { updator(item); } } 

e usalo in questo modo

  lstEmp.Update(x => x.grade = (x.desgination == "SE") ? 3 : x.grade); 

In realtà, la tua chiamata Select esistente sta modificando gli stessi oggetti originali – non sta creando nuovi oggetti dipendenti. Cosa ti fa pensare che stia creando nuove istanze di Employee ? Dopo tutto, non hai un new Employee ovunque all’interno dell’espressione lambda.

Puoi scorrere i risultati della chiamata Select senza mai chiamare ToList e in seguito continueresti a vedere le modifiche. Ciò significa che la tua proiezione ha effetti collaterali – in genere è una ctriggers idea. Però devi fare qualcosa di iterato sui risultati della proiezione. Per esempio, chiamare Count() lo farebbe, ad esempio. Le query LINQ utilizzano l’esecuzione posticipata in molti casi: non applicano la proiezione / predicato / ecc finché non è necessario il risultato.

LINQ è progettato per funzionare in modo funzionale: gli effetti collaterali sono scoraggiati, proprio come non ci si aspetterebbe una normale query SELECT su un database per modificare il contenuto della tabella che sta interrogando. Il codice privo di effetti collaterali è ottimo in termini di leggibilità e capacità di ragionare sul codice.

Se si desidera modificare i valori anziché crearne di nuovi, suggerirei invece un semplice ciclo foreach . Non è ciò per cui è stato progettato LINQ. Tuttavia, cercherò personalmente di attenermi a tipi immutabili, usare LINQ e misurare le prestazioni mentre procedete – sospetto che in molti casi non sia così male come pensate.

Direi che LINQ viene utilizzato principalmente per la selezione dei dati una volta ottenuti i dati, è ansible utilizzare il costrutto ForEach per aggiornare i dati

 lstEmp = lstEmp.Select(X => new Employee { desgination =X.desgination , grade =X.desgination=="SE"?3:X.grade , id=X.id , name =X.name }).ToList();