假设我有一个这样的业务对象,
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时它会每次生成新的employee对象,而不是更新现有的lstEmp,所以我必须将更新的列表重新分配给lstEmp。
在我看来,它会影响频繁更新大型更新时的性能。有解决方法吗?
答案 0 :(得分:18)
实际上,您现有的Select
调用 修改原始对象本身 - 它不会创建新的员工对象。是什么让你认为是创建新的Employee
实例?毕竟,你没有在lambda表达式中的任何地方new Employee
。
您可以在不调用Select
的情况下迭代调用ToList
的结果,之后您仍会看到更改。这意味着您的投影具有副作用 - 这通常是一个坏主意。你必须让某些东西迭代投影的结果。例如,只需拨打Count()
即可。在许多情况下,LINQ查询使用延迟执行:在需要结果之前,它们不应用投影/谓词/等。
LINQ旨在以功能性方式工作:不鼓励使用副作用,就像您不希望数据库上的普通SELECT查询更改其查询的表的内容一样。无副作用代码在可读性和推理代码的能力方面非常出色。
如果您想更改值而不是创建新值,我建议使用简单的foreach
循环。这不是LINQ的设计目标。但是,我会亲自尝试坚持不可变类型,使用LINQ,并在你去的时候测量性能 - 我怀疑你会发现在很多情况下它并没有你想象的那么糟糕。
答案 1 :(得分:10)
我认为默认的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);
答案 2 :(得分:1)
我会说LINQ主要用于在获取数据后选择数据,可以使用ForEach构造来更新数据
答案 3 :(得分:-2)
lstEmp = lstEmp.Select(X => new Employee
{
desgination =X.desgination ,
grade =X.desgination=="SE"?3:X.grade ,
id=X.id ,
name =X.name
}).ToList();