【问题标题】:Simple way to update IEnumerable objects using LINQ使用 LINQ 更新 IEnumerable 对象的简单方法
【发布时间】: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。

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

【问题讨论】:

标签: c# linq


【解决方案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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-03
        • 1970-01-01
        相关资源
        最近更新 更多