2014-11-05 16 views
11

In C#, se ho un List<T> e ho un oggetto di tipo T, come posso sostituire un articolo specifico nello List<T> con l'oggetto di tipo T?Sostituire un oggetto in un elenco di oggetti

Ecco che cosa ho provato:

List<CustomListItem> customListItems = new List<CustomListItem>(); 
CustomListItem customListItem1 = new CustomListItem() { name = "Item 1", date = DateTime.MinValue}; 
CustomListItem customListItem2 = new CustomListItem() { name = "Item 2", date = DateTime.MinValue }; 
CustomListItem customListItem3 = new CustomListItem() { name = "Item 3", date = DateTime.MinValue }; 

customListItems.Add(customListItem1); 
customListItems.Add(customListItem2); 
customListItems.Add(customListItem3); 

CustomListItem newCustomListItem = new CustomListItem() { name = "Item 4", date = DateTime.Now }; 

customListItem2 = customListItems.Where(i=> i.name == "Item 2").First(); 
customListItem2 = newCustomListItem; 

Nel codice di cui sopra, voglio sostituire la customListItem2 con l'newCustomListItem.

Devo rimuovere l'elemento nell'elenco e quindi inserire il nuovo elemento? Non posso fare un semplice incarico di customListItem2 = newCustomListItem?

Qual è il modo più efficiente di sostituire un elemento in un elenco con un altro elemento?

Grazie in anticipo

+0

Sono state prese delle http: // StackOverflow. com/domande/17188966/how-to-replace-list-item-in-best-way? – haim770

+0

Oltre alle soluzioni già pubblicate, è necessario implementare un Equals/GetHashCode per il proprio tipo personalizzato, altrimenti l'operazione Where/Index potrebbe non riuscire a trovare l'elemento giusto. – HimBromBeere

risposta

24

si deve sostituire l'oggetto, non il valore di customListItem2. Basta sostituire seguente:

customListItem2 = customListItems.Where(i=> i.name == "Item 2").First(); 
customListItem2 = newCustomListItem; 

Con questo:

customListItem2 = customListItems.Where(i=> i.name == "Item 2").First(); 
var index = customListItems.IndexOf(customListItem2); 

if(index != -1) 
    customListItems[index] = newCustomListItem; 

Edit:

Come Roman R. dichiarato in un commento, è possibile sostituire il .Where(predicate).First() da un semplice First(predicate):

customListItem2 = customListItems.First(i=> i.name == "Item 2"); 
+0

Grazie. Bello e semplice – user3736648

+1

È possibile sostituire il .Where con .First in primo luogo ed eliminarlo dalla fine. Sarà lo stesso risultato ma con un codice più pulito e più veloce. Fai come segue: customListItem2 = customListItems.First (i => i.name == "Item 2"); –

+0

@ ROMAN. grazie per il suggerimento, ho modificato la mia risposta. :) – Abbas

7
var customListItems = new List<CustomListItem>(); 
var customListItem1 = new CustomListItem() { name = "Item 1", date = DateTime.MinValue }; 
var customListItem2 = new CustomListItem() { name = "Item 2", date = DateTime.MinValue }; 
var customListItem3 = new CustomListItem() { name = "Item 3", date = DateTime.MinValue }; 

customListItems.Add(customListItem1); 
customListItems.Add(customListItem2); 
customListItems.Add(customListItem3); 

var newCustomListItem = new CustomListItem() { name = "Item 4", date = DateTime.Now }; 

customListItems[customListItems.FindIndex(x => x.name == "Item 2")] = newCustomListItem; 

o

public static class ListExtensions 
{ 
    public static void Replace<T>(this List<T> list, Predicate<T> oldItemSelector , T newItem) 
    { 
     //check for different situations here and throw exception 
     //if list contains multiple items that match the predicate 
     //or check for nullability of list and etc ... 
     var oldItemIndex = list.FindIndex(oldItemSelector); 
     list[oldItemIndex] = newItem; 
    } 
} 

e poi

customListItems.Replace(x => x.name == "Item 2", newCustomListItem); 
+0

L'approccio dell'estensione utilizza la riflessione? È certamente più conveniente con questo codice, e ho seguito questa strada. Mi stavo solo chiedendo di qualsiasi colpo di performance. – dunwan

+0

No, non usa la riflessione. @ dunwan – dotctor

+0

Con questa soluzione l'elenco viene eseguito solo una volta. Con quello nella risposta accettata due volte. Ma spesso o di solito il caso non trovato deve essere gestito. Se l'articolo non viene trovato, FindIndex restituisce -1. – noox

1

se sequenza di elenco non importa a voi allora si può provare questo

CustomListItem newCustomListItem = new CustomListItem() { name = "Item 4", date = DateTime.Now }; 

customListItem2 = customListItems.Where(i=> i.name == "Item 2").First(); 

customListItems.Remove(customListItem2); 
customListItems.Add(newCustomListItem);