使用 LINQ 更新 IEnumerable 对象的简单方法

Posted

技术标签:

【中文标题】使用 LINQ 更新 IEnumerable 对象的简单方法【英文标题】:Simple way to update IEnumerable objects using LINQ 【发布时间】:2011-04-25 05:40:09 【问题描述】:

假设我有一个这样的业务对象,

class Employee
    
        public string name;
        public int id;
        public string desgination;
        public int grade;
    

    List<Employee> lstEmp = new List<Employee>()
        
            new Employee()  name="A",desgination="SE",id=1,
            new Employee()  name="b",desgination="TL",id=2,
            new Employee()  name="c",desgination="PL",id=3,
            new Employee()  name="d",desgination="SE",id=4,
            new Employee()  name="e",desgination="SSE",id=5,
        ;

如果我想将员工等级更新为 3,其指定为“SE”,那么我必须写这样的东西

lstEmp=lstEmp.Select(x =>
            
                x.grade = (x.desgination == "SE") ? 3 : x.grade;
                    return x;
            ).ToList();

但是在这里,当使用 select 时,它每次都会生成新的员工对象,而不是更新现有的 lstEmp,所以我必须将更新的列表重新分配给 lstEmp。

在我看来,频繁更新大型更新会影响性能。有解决办法吗?

【问题讨论】:

这个问题有一些很好的答案:***.com/questions/398871/… 【参考方案1】:

实际上,您现有的Select 调用正在修改原始对象本身 - 它不是创建新的员工对象。是什么让您认为它正在创建新的Employee 实例?毕竟,您在 lambda 表达式中的任何地方都没有 new Employee

您可以遍历调用Select 的结果而无需调用ToList,之后您仍会看到更改。这意味着您的投影有副作用 - 这通常是个坏主意。不过,您确实必须让 something 迭代投影的结果。例如,只需调用Count() 即可。 LINQ 查询在许多情况下使用延迟执行:它们在需要结果之前不会应用投影/谓词/等。

LINQ 旨在以功能性方式工作:不鼓励副作用,就像您不希望对数据库进行正常的 SELECT 查询来更改它正在查询的表的内容一样。无副作用的代码在可读性和代码推理能力方面非常出色。

如果您想更改值而不是创建新值,我建议改为使用简单的foreach 循环。这不是 LINQ 的设计目的。但是,我个人会尝试坚持不可变类型,使用 LINQ,并随时测量性能 - 我怀疑您会发现在许多情况下它并没有您想象的那么糟糕。

【讨论】:

【参考方案2】:

我相信默认的 LINQ 方法不支持内联更新。但您可以创建自己的扩展方法来实现这一点

  public static void Update<TSource>(this IEnumerable<TSource> outer, Action<TSource> updator)
        
            foreach (var item in outer)
            
                updator(item);
            


        

并像这样使用它

 lstEmp.Update(x => x.grade = (x.desgination == "SE") ? 3 : x.grade);

【讨论】:

ForEach() 不可能,因为它是 foreach 中的只读状态。【参考方案3】:

我想说 LINQ 主要用于数据的选择,一旦你得到数据,你可以使用 ForEach 构造来更新数据

【讨论】:

【参考方案4】:
lstEmp = lstEmp.Select(X => new Employee
        
            desgination =X.desgination ,
            grade =X.desgination=="SE"?3:X.grade ,
            id=X.id ,
            name =X.name 
        ).ToList();

【讨论】:

以上是关于使用 LINQ 更新 IEnumerable 对象的简单方法的主要内容,如果未能解决你的问题,请参考以下文章

C#中的LINQ 基础

LINQ

LINQ学习笔记

如何使用 LINQ 修改 IEnumerable 以避免 foreach 循环? [复制]

译使用 LINQ 合并 IEnumerable 序列

linq-IEnumerable,IEnumerator