Cách cập nhật một đối tượng trong Danh sách <> trong C #


81

Tôi có một List<>đối tượng tùy chỉnh.

Tôi cần tìm một đối tượng trong danh sách này theo một số thuộc tính là duy nhất và cập nhật một thuộc tính khác của đối tượng này.

Cách nhanh nhất để làm điều đó là gì?

Câu trả lời:


108

Sử dụng Linq để tìm đối tượng bạn có thể làm:

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

Nhưng trong trường hợp này, bạn có thể muốn lưu Danh sách vào Từ điển và sử dụng điều này thay thế:

// ... 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
Cảm ơn CKoenig, điều này sẽ nhận được một tham chiếu đến objhoặc giá trị (bản sao)? nói cách khác, đối tượng bên trong danh sách có bị thay đổi không?
Burjua

4
Tôi nghĩ rằng điều này sẽ không làm việc nếu đối tượng là loại cấu trúc, làm cho nó một lớp :)
Sara S.

27
Bởi vì bạn có một danh sách các đối tượng tùy chỉnh (giả sử nó là một lớp chứ không phải một cấu trúc), bạn đang xử lý một kiểu tham chiếu, nó sẽ là một tham chiếu đến đối tượng đó và việc sửa đổi nó sẽ "tồn tại" - nó sẽ sửa đổi đối tượng trong bộ sưu tập.
Matt Roberts

1
điều này sẽ tìm thấy tham chiếu (vì vậy có nó sẽ là đối tượng trong danh sách) và nó cũng sẽ hoạt động với cấu trúc - nhưng thành thật mà nói, tôi đã phải cố gắng để chắc chắn ở đó - nhưng tôi không hiểu tại sao không phải là ATM
Carsten

2
@CKoenig - Nó sẽ không làm việc với cấu trúc, bổ sung một phản ứng dưới đây với mã ví dụ để chứng minh
Matt Roberts

29

Chỉ để thêm vào phản hồi của CKoenig. Câu trả lời của anh ấy sẽ hoạt động miễn là lớp bạn đang xử lý là một loại tham chiếu (như một lớp). Nếu đối tượng tùy chỉnh là một cấu trúc, thì đây là một kiểu giá trị và kết quả của .FirstOrDefaultsẽ cung cấp cho bạn một bản sao cục bộ của nó, có nghĩa là nó sẽ không tồn tại trở lại bộ sưu tập, như ví dụ này cho thấy:

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

Mã kiểm tra:

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

Sản lượng là 10,1,145

Thay đổi cấu trúc thành một lớp và đầu ra là 10,12,145

HTH


được rồi cảm ơn. tôi đoán rằng bạn sẽ nhận được một tham chiếu đến cấu trúc thay vì một bản sao cục bộ.
Carsten

18

hoặc không có linq

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

1
Vâng, đây là câu trả lời rõ ràng, nhưng tôi không muốn sử dụng foreach, tôi đoán đây là cách chậm nhất để làm điều đó
Burjua

Bất cứ ai có thể nhận xét về việc liệu phương pháp LINQ ở trên có thực sự hiệu quả hơn phương pháp này không?
pseudocoder

6
Nếu có bất kỳ sự khác biệt nào, phiên bản linq có lẽ chậm hơn.
Erix

7
@Burjua Nhận thức là chúng ta có thể thấy vòng lặp thực sự xảy ra trong khối foreach, trong khi ở Linq / Lambda thì không, vì vậy chúng tôi cho rằng foreach chậm hơn và cố gắng tránh nó. Thực tế là các vòng lặp foreach / for / while nhanh hơn nhiều.
harsimranb

Chậm hơn / nhanh hơn, tôi không biết là cái nào ... nhưng trong trường hợp của tôi, dù sao thì tôi cũng đang xử lý các bản ghi nhỏ và không muốn nghĩ về nó nhiều. Điều này đã hiệu quả! Liên lạc tốt đẹp với sự phá vỡ;
Anthony Griggs

9

Cũng có thể thử.

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

3
Này làm việc với một danh sách hoặc một mảng, nhưng không phải là một IEnumerable
Lord Darth Vader

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

1
Không cần xóa đối tượng khỏi danh sách và chèn lại nó (rất kém hiệu quả). Đối tượng là các kiểu tham chiếu. Khi bạn có tham chiếu đến đối tượng, chỉ cần cập nhật đối tượng vì nó là một và giống với đối tượng trong danh sách.
humbads

Thêm một gợi ý. FindIndex có thể trả về -1, trong trường hợp đó, ElementAt sẽ đưa ra một ngoại lệ.
humbads

4

Bạn có thể làm những việc như sau:

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

Đây là một khám phá mới ngày hôm nay - sau khi đã học bài học tham khảo lớp / cấu trúc!

Bạn có thể sử dụng Linq và "Single" nếu bạn biết mục sẽ được tìm thấy, vì Single trả về một biến ...

myList.Single(x => x.MyProperty == myValue).OtherProperty = newValue;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.