it-swarm.com.ru

Как обновить значение в списке с помощью LINQ

У меня есть список, который я хочу обновить с помощью LINQ. 

class Student
{
    private string name;
    private int marks;
    public string Name { get; set;}
    public int Marks { get; set; }
    public Student(string name, int marks)
    {
        Name = name;
        Marks = marks;
    }
}

List<Student> myList = new List<Student>();
myList.Add(new Student("John", 10));
myList.Add(new Student("Tom", 20));

Теперь я хочу обновить список с помощью LINQ так, чтобы обновлялись только отметки Джона. Я использую следующий синтаксис:

myList.Where(w => w.Name == "Tom").Select(w=> { w.Marks = 35; return w});

Но это не обновляет данные в myList. Может кто-нибудь сказать мне, где я иду не так. 

2
user3625024

LINQ предназначен для запросов, а не для обновления данных. Используйте LINQ, чтобы получить элементы, которые вы хотите изменить, а затем измените их в цикле foreach:

foreach ( var tom in myList.Where(w => w.Name == "Tom")) {
    tom.Marks = 35;
}

Демо.

22
dasblinkenlight

Как уже отмечали другие, LINQ предназначен для запроса данных, а не для обновления. 

Вы должны перебрать свой список и изменить ваши значения следующим образом:

foreach (var student in myList)
{
    if (student.Name == "Tom")
    {
        student.Marks = 35;
    }
}

Или же

foreach (var student in myList.Where(r => r.Name == "Tom"))
{
    student.Marks = 35;
}

Все, что вы думаете лучше, передает намерение использовать это. 


но вот интересная вещь:

Если у вас есть заявление вроде:

myList.Where(w => w.Name == "Tom").Select(w => w.Marks = 35).ToList();

Без присвоения результата обратно myList приведенный выше запрос изменит значение в исходном списке. Помните, это побочный эффект, и это не правильный способ обновления . Это изменение может быть объяснено передачей ссылочного параметра в метод и его изменением там. Но главное, этого всегда следует избегать . Это плохая практика и может привести к действительно запутанному коду. Используйте LINQ только для запросов. 

5
Habib

Пытаться:

myList .Where(w=> w.Name  == "dTomi").ToList().ForEach(i => i.Marks  = 35);
2
SHIBIN

Объекты хранятся в списке по ссылке, поэтому вы можете восстановить объект с помощью linq, а затем отредактировать, что будет отражать изменения в списке.

Пример

    static void Main(string[] args)
        {
            List<Entity> testList = new List<Entity>()
            {
                new Entity() {Id = 1, Text = "Text"},
                new Entity() {Id = 2, Text = "Text2"}
            };

            Console.WriteLine($"First text value:{testList[1].Text}");

            Entity entityToEdit = testList.FirstOrDefault(e => e.Id == 2);
            if (entityToEdit != null)
                entityToEdit.Text = "Hello You!!";

            Console.WriteLine($"Edited text value:{testList[1].Text}");

            Console.ReadLine();
        }

 internal class Entity
    {
        public int Id { get; set; }
        public String Text { get; set; }
    }

Протестировав приложение, вы получите следующий результат:

Первое текстовое значение: Text2

Отредактированное текстовое значение: Hello You !!

0
Final Nemael

как насчет старого доброго for цикла

for(int i = 0; i < myList.Count; i++)
if (myList[i].Name  == "Tom")
{
    myList[i].Marks = 35;
    break;
}
0
ASh

хорошо, @dasblinkenlight код должен работать, но вы также можете попробовать что-то вроде этого

 var query = from x in list
             where x.Name = yourcondition
             select new { x };
foreach(var item in query)
   item.x.FieldToUpdate = SetValue;
0
user2726374

Это немного неуклюже, но работает и не зависит от того, будет ли передана ссылка. Создает новый список на основе старого.

var myList=myList.Select(l=>new Student { 
   l.Name,
   Marks=l.Name=="Tom"?35:l.Marks}).ToList();

Или глупее

var myList=myList.Where(l=>l.Name!="Tom").Union(
  myList.Where(l=>l.Name=="Tom").Select(l=>new Student { 
   l.Name,
   Marks=35})).ToList();
0
Robert McKee

Выше может быть достигнуто, просто присваивая значение обратно в коллекцию

myList = myList
        .Where(w => w.Name == "Tom")
        .Select(w=> { w.Marks = 35; return w})
        .ToList();
0
Sathish