繁体   English   中英

如何使用LINQ更新列表中的值

[英]How to update value in a List using 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更新列表,以便仅更新John的标记。 我正在使用以下语法:

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

但这不会更新myList中的数据。 有人可以告诉我我要去哪里错了。

LINQ用于查询,而不用于更新数据。 使用LINQ来获取要修改的项目,然后在foreach循环中对其进行修改:

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

演示

正如其他人指出的那样,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仅用于查询。

尝试:

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

与其他LINQ方法一样, Select()不会更改源集合,而是返回一个新集合。

因此,您应该将该新集合分配给myList

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

或在单独的foreach循环中分配Marks属性

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

只需将值分配回集合即可实现以上目的

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

旧的for循环怎么样

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

@dasblinkenlight代码应该可以正常工作,但您也可以尝试这样的操作

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

这有点笨拙,但是有效,并且不依赖于传递引用。 它基于旧列表创建一个新列表。

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

对象通过引用存储在列表中,因此您可以通过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

编辑文字值:您好!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM