Jak zaktualizować obiekt w List <> w C #


82

Mam kilka List<>niestandardowych obiektów.

Muszę znaleźć obiekt na tej liście według jakiejś unikalnej właściwości i zaktualizować inną właściwość tego obiektu.

Jak to zrobić najszybciej?

Odpowiedzi:


109

Używając Linq, aby znaleźć obiekt, który możesz zrobić:

var obj = myList.FirstOrDefault(x => x.MyProperty == myValue);
if (obj != null) obj.OtherProperty = newValue;

Ale w tym przypadku możesz zechcieć zapisać listę w słowniku i zamiast tego użyć tego:

// ... define after getting the List/Enumerable/whatever
var dict = myList.ToDictionary(x => x.MyProperty);
// ... somewhere in code
MyObject found;
if (dict.TryGetValue(myValue, out found)) found.OtherProperty = newValue;

4
Dzięki CKoenig, czy to otrzyma odniesienie do objlub wartość (kopia)? innymi słowy, czy obiekt na liście zostanie zmieniony?
— Burjua,

4
Myślę, że to nie będzie działać, jeśli obiekt jest typu struct, sprawiają, że klasę :)
— Sara S.

27
Ponieważ masz listę obiektów niestandardowych (zakładając, że jest to klasa, a nie struktura), masz do czynienia z typem referencyjnym, będzie to odniesienie do tego obiektu i modyfikacja go „utrwali” - zmodyfikuje obiekt w kolekcja.
— Matt Roberts,

1
to znajdzie odniesienie (więc tak, będzie to obiekt na liście) i powinno również działać ze strukturami - ale szczerze mówiąc, musiałem spróbować się upewnić - ale nie widzę, dlaczego nie ATM
— Carsten

2
@CKoenig - To nie działałoby ze strukturami, dodano odpowiedź poniżej z przykładem kodu do zademonstrowania
— Matt Roberts

30

Wystarczy dodać do odpowiedzi CKoeniga. Jego odpowiedź będzie działać, o ile klasa, z którą masz do czynienia, jest typem referencyjnym (jak klasa). Jeśli obiekt niestandardowy był strukturą, jest to typ wartości, a wyniki działania .FirstOrDefaultda ci lokalną kopię tego, co oznacza, że ​​nie zostanie zachowany z powrotem w kolekcji, jak pokazano w tym przykładzie:

struct MyStruct
{
    public int TheValue { get; set; }
}

Kod testowy:

List<MyStruct> coll = new List<MyStruct> {
                                            new MyStruct {TheValue = 10},
                                            new MyStruct {TheValue = 1},
                                            new MyStruct {TheValue = 145},
                                            };
var found = coll.FirstOrDefault(c => c.TheValue == 1);
found.TheValue = 12;

foreach (var myStruct in coll)
{
    Console.WriteLine(myStruct.TheValue);
}
Console.ReadLine();

Wynik to 10,1145

Zmień strukturę na klasę, a wynik to 10,12,145

HTH


ok dzięki. przypuszczam, że zamiast lokalnej kopii otrzymasz odniesienie do struktury.
— Carsten,

18

lub bez linq

foreach(MyObject obj in myList)
{
   if(obj.prop == someValue)
   {
     obj.otherProp = newValue;
     break;
   }
}

1
Tak, to oczywista odpowiedź, ale nie chcę używać wszystkich, myślę, że jest to najwolniejszy sposób
— Burjua

Czy ktoś może wypowiedzieć się na temat tego, czy powyższa metoda LINQ jest rzeczywiście bardziej wydajna niż ta?
— pseudocoder,

6
Jeśli jest jakaś różnica, wersja linq jest prawdopodobnie wolniejsza.
— Erix,

7
@Burjua Uważa się, że możemy zobaczyć rzeczywistą pętlę zachodzącą w bloku foreach, podczas gdy w Linq / Lambda nie, więc zakładamy, że foreach jest wolniejsze i staramy się tego uniknąć. Rzeczywistość jest zawsze / dla /, podczas gdy pętle są znacznie szybsze.
— harsimranb

Cóż, wolniej / szybciej, nie wiem które ... ale w moim przypadku i tak miałem do czynienia z małymi płytami i nie chciałem zbytnio o tym myśleć. To zadziałało! Miły akcent z przerwą;
— Anthony Griggs

9

Można też spróbować.

 _lstProductDetail.Where(S => S.ProductID == "")
        .Select(S => { S.ProductPcs = "Update Value" ; return S; }).ToList();

3
Działa to z listą lub tablicą, ale nie z IEnumerable
— Lord Darth Vader

6
var itemIndex = listObject.FindIndex(x => x == SomeSpecialCondition());
var item = listObject.ElementAt(itemIndex);
item.SomePropYouWantToChange = "yourNewValue";

2
Nie ma potrzeby usuwania obiektu z listy i ponownego wstawiania go (bardzo nieefektywne). Obiekty są typami referencyjnymi. Gdy masz już odniesienie do obiektu, po prostu zaktualizuj obiekt, ponieważ jest taki sam jak obiekt na liście.
— humbads

1
Jeszcze jedna sugestia. FindIndex może zwrócić -1, w takim przypadku ElementAt zgłosi wyjątek.
— humbads

4

Możesz zrobić coś takiego:

if (product != null) {
    var products = Repository.Products;
    var indexOf = products.IndexOf(products.Find(p => p.Id == product.Id));
    Repository.Products[indexOf] = product;
    // or 
    Repository.Products[indexOf].prop = product.prop;
}

0

To było dziś nowe odkrycie - po zapoznaniu się z lekcją referencyjną dotyczącą klasy / struktury!

Możesz użyć Linq i „Single”, jeśli wiesz, że element zostanie znaleziony, ponieważ Single zwraca zmienną ...

myList.Single(x => x.MyProperty == myValue).OtherProperty = newValue;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.