Як оновити об’єкт у списку <> на C #


82

Я маю List<> спеціальні об'єкти.

Мені потрібно знайти об’єкт у цьому списку за якоюсь унікальною властивістю та оновити іншу властивість цього об’єкта.

Який найшвидший спосіб це зробити?

Відповіді:


109

Використання Linq для пошуку об’єкта, який ви можете зробити:

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

Але в цьому випадку, можливо, ви захочете зберегти Список у словнику та використовувати замість цього:

// ... 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
Дякую CKoenig, чи отримає це посилання objабо значення (копія)? іншими словами, чи буде змінено об’єкт у списку?
Бурджуа,

4
Я думаю, що це не спрацювало б, якщо об’єкт має структуру типу, зробіть його класом :)
Сара С.

27
Оскільки у вас є список користувацьких об'єктів (припускаючи, що це клас, а не структура), ви маєте справу з посилальним типом, він буде посиланням на цей об'єкт, а його модифікація буде "зберігатися" - це змінить об'єкт у зібрання.
Метт Робертс,

1
це буде знайти посилання (та так воно буде об'єктом в списку) , і він повинен працювати з дуже структурами - але, чесно кажучи , я повинен був спробувати бути впевнені, - але я не розумію , чому немає ATM
Карстен

2
@CKoenig - Це не буде працювати зі структурами, додав відповідь нижче із прикладом коду для демонстрації
Метт Робертс

30

Просто щоб додати відповідь ККеніґа. Його відповідь буде працювати, доки клас, з яким ви маєте справу, є референсним типом (як клас). Якщо користувальницький об'єкт був структурою, це тип значення, і результати результатів .FirstOrDefaultдадуть вам локальну копію цього, що означатиме, що він не збережеться назад до колекції, як показано в цьому прикладі:

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

Тестовий код:

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();

Вихід 10,1145

Змініть структуру на клас, і результат буде 10,12,145

HTH


добре, дякую. я здогадуюсь, ви отримаєте посилання на структуру, а не на локальну копію.
Карстен

18

або без посилання

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

1
Так, це очевидна відповідь, але я не хочу використовувати foreach, мабуть, це найповільніший спосіб це зробити
Бурджуа

Хтось може прокоментувати, чи насправді метод LINQ насправді ефективніший за цей?
псевдокодер

6
Якщо є якась різниця, версія linq, ймовірно, повільніша.
Ерікс,

7
@Burjua Уявлення полягає в тому, що ми можемо бачити фактичний цикл, що відбувається в блоці foreach, тоді як у Linq / Lambda цього не відбувається, тому ми припускаємо, що foreach працює повільніше і намагаємося цього уникнути. Реальність - це foreach / for /, тоді як цикли набагато швидші.
harsimranb

Ну повільніше / швидше, я не знаю, який ... але в моєму випадку я все одно мав справу з невеликими записами і не хотів над цим думати. Це спрацювало! Приємний дотик з перервою;
Ентоні Гріггс,

9

Можна також спробувати.

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

3
Це працює зі списком або масивом, але не з незліченною кількістю
лорд Дарт Вейдер,

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

2
Не потрібно вилучати об’єкт зі списку та вставляти його повторно (дуже неефективно). Об'єкти є еталонними типами. Отримавши посилання на об’єкт, просто оновіть об’єкт, оскільки він є одним і тим же, як об’єкт у списку.
humbads

1
Ще одна пропозиція. FindIndex може повернути -1, і в цьому випадку ElementAt видасть виняток.
humbads

4

Ви можете робити щось таке:

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

Сьогодні це було нове відкриття - після того, як ви вивчили довідковий урок класу / структури!

Ви можете використовувати Linq та "Single", якщо знаєте, що елемент буде знайдений, оскільки Single повертає змінну ...

myList.Single(x => x.MyProperty == myValue).OtherProperty = newValue;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.